authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-24 10:44:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-24 10:44:41-07:00
loge86cee258cb0eefca14a94f6b3abb39e8a5f2ef9
tree6d9aa3b21685b1581787246f953db94cdb486693
parent224fbb23c44628b215662c6199dff11cc2851f04
parent8530b6b7242ebf43b5cb4ae3a2644593f4961a5e

Merge remote-tracking branch 'origin/master' into stage2-whole-file-astgen

In particular I wanted the change that makes `suspend;` illegal in the parser.

73 files changed, 1162 insertions(+), 470 deletions(-)

.gitattributes+6-6
...@@ -3,9 +3,9 @@...@@ -3,9 +3,9 @@
3langref.html.in text eol=lf3langref.html.in text eol=lf
4deps/SoftFloat-3e/*.txt text eol=crlf4deps/SoftFloat-3e/*.txt text eol=crlf
55
6deps/* linguist-vendored6deps/** linguist-vendored
7lib/include/* linguist-vendored7lib/include/** linguist-vendored
8lib/libc/* linguist-vendored8lib/libc/** linguist-vendored
9lib/libcxx/* linguist-vendored9lib/libcxx/** linguist-vendored
10lib/libcxxabi/* linguist-vendored10lib/libcxxabi/** linguist-vendored
11lib/libunwind/* linguist-vendored11lib/libunwind/** linguist-vendored
build.zig+1
...@@ -267,6 +267,7 @@ pub fn build(b: *Builder) !void {...@@ -267,6 +267,7 @@ pub fn build(b: *Builder) !void {
267 test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/std.zig", "std", "Run the standard library tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir));267 test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/std.zig", "std", "Run the standard library tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir));
268268
269 test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir));269 test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir));
270 test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/c.zig", "minilibc", "Run the mini libc tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir));
270271
271 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));272 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
272 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));273 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));
ci/drone/linux_script+1-3
...@@ -23,13 +23,11 @@ cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_INSTALL_PREFIX=$DISTDIR" -DZIG_STAT...@@ -23,13 +23,11 @@ cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_INSTALL_PREFIX=$DISTDIR" -DZIG_STAT
2323
24samu install24samu install
25# run-translated-c tests are skipped due to: https://github.com/ziglang/zig/issues/853725# run-translated-c tests are skipped due to: https://github.com/ziglang/zig/issues/8537
26# stage2 tests are skipped due to: https://github.com/ziglang/zig/issues/8545
27./zig build test \26./zig build test \
28 -Dskip-release \27 -Dskip-release \
29 -Dskip-non-native \28 -Dskip-non-native \
30 -Dskip-compile-errors \29 -Dskip-compile-errors \
31 -Dskip-run-translated-c \30 -Dskip-run-translated-c
32 -Dskip-stage2-tests
3331
34if [ -z "$DRONE_PULL_REQUEST" ]; then32if [ -z "$DRONE_PULL_REQUEST" ]; then
35 mv ../LICENSE "$DISTDIR/"33 mv ../LICENSE "$DISTDIR/"
doc/langref.html.in+15-7
...@@ -6509,7 +6509,7 @@ test "suspend with no resume" {...@@ -6509,7 +6509,7 @@ test "suspend with no resume" {
65096509
6510fn func() void {6510fn func() void {
6511 x += 1;6511 x += 1;
6512 suspend;6512 suspend {}
6513 // This line is never reached because the suspend has no matching resume.6513 // This line is never reached because the suspend has no matching resume.
6514 x += 1;6514 x += 1;
6515}6515}
...@@ -6574,7 +6574,7 @@ fn testResumeFromSuspend(my_result: *i32) void {...@@ -6574,7 +6574,7 @@ fn testResumeFromSuspend(my_result: *i32) void {
6574 resume @frame();6574 resume @frame();
6575 }6575 }
6576 my_result.* += 1;6576 my_result.* += 1;
6577 suspend;6577 suspend {}
6578 my_result.* += 1;6578 my_result.* += 1;
6579}6579}
6580 {#code_end#}6580 {#code_end#}
...@@ -6613,7 +6613,7 @@ fn amain() void {...@@ -6613,7 +6613,7 @@ fn amain() void {
6613}6613}
66146614
6615fn func() void {6615fn func() void {
6616 suspend;6616 suspend {}
6617}6617}
6618 {#code_end#}6618 {#code_end#}
6619 <p>6619 <p>
...@@ -6915,7 +6915,7 @@ test "async fn pointer in a struct field" {...@@ -6915,7 +6915,7 @@ test "async fn pointer in a struct field" {
6915fn func(y: *i32) void {6915fn func(y: *i32) void {
6916 defer y.* += 2;6916 defer y.* += 2;
6917 y.* += 1;6917 y.* += 1;
6918 suspend;6918 suspend {}
6919}6919}
6920 {#code_end#}6920 {#code_end#}
6921 {#header_close#}6921 {#header_close#}
...@@ -7498,13 +7498,13 @@ test "main" {...@@ -7498,13 +7498,13 @@ test "main" {
7498 {#header_close#}7498 {#header_close#}
74997499
7500 {#header_open|@export#}7500 {#header_open|@export#}
7501 <pre>{#syntax#}@export(target: anytype, comptime options: std.builtin.ExportOptions) void{#endsyntax#}</pre>7501 <pre>{#syntax#}@export(identifier, comptime options: std.builtin.ExportOptions) void{#endsyntax#}</pre>
7502 <p>7502 <p>
7503 Creates a symbol in the output object file.7503 Creates a symbol in the output object file.
7504 </p>7504 </p>
7505 <p>7505 <p>
7506 This function can be called from a {#link|comptime#} block to conditionally export symbols.7506 This function can be called from a {#link|comptime#} block to conditionally export symbols.
7507 When {#syntax#}target{#endsyntax#} is a function with the C calling convention and7507 When {#syntax#}identifier{#endsyntax#} is a function with the C calling convention and
7508 {#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to7508 {#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to
7509 the {#syntax#}export{#endsyntax#} keyword used on a function:7509 the {#syntax#}export{#endsyntax#} keyword used on a function:
7510 </p>7510 </p>
...@@ -7531,6 +7531,14 @@ export fn @"A function name that is a complete sentence."() void {}...@@ -7531,6 +7531,14 @@ export fn @"A function name that is a complete sentence."() void {}
7531 {#see_also|Exporting a C Library#}7531 {#see_also|Exporting a C Library#}
7532 {#header_close#}7532 {#header_close#}
75337533
7534 {#header_open|@extern#}
7535 <pre>{#syntax#}@extern(T: type, comptime options: std.builtin.ExternOptions) *T{#endsyntax#}</pre>
7536 <p>
7537 Creates a reference to an external symbol in the output object file.
7538 </p>
7539 {#see_also|@export#}
7540 {#header_close#}
7541
7534 {#header_open|@fence#}7542 {#header_open|@fence#}
7535 <pre>{#syntax#}@fence(order: AtomicOrder){#endsyntax#}</pre>7543 <pre>{#syntax#}@fence(order: AtomicOrder){#endsyntax#}</pre>
7536 <p>7544 <p>
...@@ -7640,7 +7648,7 @@ test "heap allocated frame" {...@@ -7640,7 +7648,7 @@ test "heap allocated frame" {
7640}7648}
76417649
7642fn func() void {7650fn func() void {
7643 suspend;7651 suspend {}
7644}7652}
7645 {#code_end#}7653 {#code_end#}
7646 {#header_close#}7654 {#header_close#}
lib/std/atomic/bool.zig+1-1
...@@ -28,7 +28,7 @@ pub const Bool = extern struct {...@@ -28,7 +28,7 @@ pub const Bool = extern struct {
28 return @atomicRmw(bool, &self.unprotected_value, .Xchg, operand, ordering);28 return @atomicRmw(bool, &self.unprotected_value, .Xchg, operand, ordering);
29 }29 }
3030
31 pub fn load(self: *Self, comptime ordering: std.builtin.AtomicOrder) bool {31 pub fn load(self: *const Self, comptime ordering: std.builtin.AtomicOrder) bool {
32 switch (ordering) {32 switch (ordering) {
33 .Unordered, .Monotonic, .Acquire, .SeqCst => {},33 .Unordered, .Monotonic, .Acquire, .SeqCst => {},
34 else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),34 else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),
lib/std/atomic/int.zig+2-2
...@@ -31,7 +31,7 @@ pub fn Int(comptime T: type) type {...@@ -31,7 +31,7 @@ pub fn Int(comptime T: type) type {
31 return @atomicRmw(T, &self.unprotected_value, op, operand, ordering);31 return @atomicRmw(T, &self.unprotected_value, op, operand, ordering);
32 }32 }
3333
34 pub fn load(self: *Self, comptime ordering: builtin.AtomicOrder) T {34 pub fn load(self: *const Self, comptime ordering: builtin.AtomicOrder) T {
35 switch (ordering) {35 switch (ordering) {
36 .Unordered, .Monotonic, .Acquire, .SeqCst => {},36 .Unordered, .Monotonic, .Acquire, .SeqCst => {},
37 else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),37 else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),
...@@ -59,7 +59,7 @@ pub fn Int(comptime T: type) type {...@@ -59,7 +59,7 @@ pub fn Int(comptime T: type) type {
59 return self.rmw(.Sub, 1, .SeqCst);59 return self.rmw(.Sub, 1, .SeqCst);
60 }60 }
6161
62 pub fn get(self: *Self) T {62 pub fn get(self: *const Self) T {
63 return self.load(.SeqCst);63 return self.load(.SeqCst);
64 }64 }
6565
lib/std/build.zig+5
...@@ -1386,6 +1386,8 @@ pub const LibExeObjStep = struct {...@@ -1386,6 +1386,8 @@ pub const LibExeObjStep = struct {
1386 /// safely garbage-collected during the linking phase.1386 /// safely garbage-collected during the linking phase.
1387 link_function_sections: bool = false,1387 link_function_sections: bool = false,
13881388
1389 linker_allow_shlib_undefined: ?bool = null,
1390
1389 /// Uses system Wine installation to run cross compiled Windows build artifacts.1391 /// Uses system Wine installation to run cross compiled Windows build artifacts.
1390 enable_wine: bool = false,1392 enable_wine: bool = false,
13911393
...@@ -2338,6 +2340,9 @@ pub const LibExeObjStep = struct {...@@ -2338,6 +2340,9 @@ pub const LibExeObjStep = struct {
2338 if (self.link_function_sections) {2340 if (self.link_function_sections) {
2339 try zig_args.append("-ffunction-sections");2341 try zig_args.append("-ffunction-sections");
2340 }2342 }
2343 if (self.linker_allow_shlib_undefined) |x| {
2344 try zig_args.append(if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");
2345 }
2341 if (self.single_threaded) {2346 if (self.single_threaded) {
2342 try zig_args.append("--single-threaded");2347 try zig_args.append("--single-threaded");
2343 }2348 }
lib/std/crypto.zig+1-1
...@@ -154,7 +154,7 @@ pub const random = &@import("crypto/tlcsprng.zig").interface;...@@ -154,7 +154,7 @@ pub const random = &@import("crypto/tlcsprng.zig").interface;
154154
155const std = @import("std.zig");155const std = @import("std.zig");
156156
157pub const Error = @import("crypto/error.zig").Error;157pub const errors = @import("crypto/errors.zig");
158158
159test "crypto" {159test "crypto" {
160 const please_windows_dont_oom = std.Target.current.os.tag == .windows;160 const please_windows_dont_oom = std.Target.current.os.tag == .windows;
lib/std/crypto/25519/curve25519.zig+12-8
...@@ -4,7 +4,11 @@...@@ -4,7 +4,11 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const Error = std.crypto.Error;7const crypto = std.crypto;
8
9const IdentityElementError = crypto.errors.IdentityElementError;
10const NonCanonicalError = crypto.errors.NonCanonicalError;
11const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
812
9/// Group operations over Curve25519.13/// Group operations over Curve25519.
10pub const Curve25519 = struct {14pub const Curve25519 = struct {
...@@ -29,12 +33,12 @@ pub const Curve25519 = struct {...@@ -29,12 +33,12 @@ pub const Curve25519 = struct {
29 pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };33 pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };
3034
31 /// Check that the encoding of a Curve25519 point is canonical.35 /// Check that the encoding of a Curve25519 point is canonical.
32 pub fn rejectNonCanonical(s: [32]u8) Error!void {36 pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
33 return Fe.rejectNonCanonical(s, false);37 return Fe.rejectNonCanonical(s, false);
34 }38 }
3539
36 /// Reject the neutral element.40 /// Reject the neutral element.
37 pub fn rejectIdentity(p: Curve25519) Error!void {41 pub fn rejectIdentity(p: Curve25519) IdentityElementError!void {
38 if (p.x.isZero()) {42 if (p.x.isZero()) {
39 return error.IdentityElement;43 return error.IdentityElement;
40 }44 }
...@@ -45,7 +49,7 @@ pub const Curve25519 = struct {...@@ -45,7 +49,7 @@ pub const Curve25519 = struct {
45 return p.dbl().dbl().dbl();49 return p.dbl().dbl().dbl();
46 }50 }
4751
48 fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) Error!Curve25519 {52 fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) IdentityElementError!Curve25519 {
49 var x1 = p.x;53 var x1 = p.x;
50 var x2 = Fe.one;54 var x2 = Fe.one;
51 var z2 = Fe.zero;55 var z2 = Fe.zero;
...@@ -86,7 +90,7 @@ pub const Curve25519 = struct {...@@ -86,7 +90,7 @@ pub const Curve25519 = struct {
86 /// way to use Curve25519 for a DH operation.90 /// way to use Curve25519 for a DH operation.
87 /// Return error.IdentityElement if the resulting point is91 /// Return error.IdentityElement if the resulting point is
88 /// the identity element.92 /// the identity element.
89 pub fn clampedMul(p: Curve25519, s: [32]u8) Error!Curve25519 {93 pub fn clampedMul(p: Curve25519, s: [32]u8) IdentityElementError!Curve25519 {
90 var t: [32]u8 = s;94 var t: [32]u8 = s;
91 scalar.clamp(&t);95 scalar.clamp(&t);
92 return try ladder(p, t, 255);96 return try ladder(p, t, 255);
...@@ -96,16 +100,16 @@ pub const Curve25519 = struct {...@@ -96,16 +100,16 @@ pub const Curve25519 = struct {
96 /// Return error.IdentityElement if the resulting point is100 /// Return error.IdentityElement if the resulting point is
97 /// the identity element or error.WeakPublicKey if the public101 /// the identity element or error.WeakPublicKey if the public
98 /// key is a low-order point.102 /// key is a low-order point.
99 pub fn mul(p: Curve25519, s: [32]u8) Error!Curve25519 {103 pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 {
100 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;104 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;
101 _ = ladder(p, cofactor, 4) catch return error.WeakPublicKey;105 _ = ladder(p, cofactor, 4) catch return error.WeakPublicKey;
102 return try ladder(p, s, 256);106 return try ladder(p, s, 256);
103 }107 }
104108
105 /// Compute the Curve25519 equivalent to an Edwards25519 point.109 /// Compute the Curve25519 equivalent to an Edwards25519 point.
106 pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) Error!Curve25519 {110 pub fn fromEdwards25519(p: crypto.ecc.Edwards25519) IdentityElementError!Curve25519 {
107 try p.clearCofactor().rejectIdentity();111 try p.clearCofactor().rejectIdentity();
108 const one = std.crypto.ecc.Edwards25519.Fe.one;112 const one = crypto.ecc.Edwards25519.Fe.one;
109 const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd)113 const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd)
110 return Curve25519{ .x = x };114 return Curve25519{ .x = x };
111 }115 }
lib/std/crypto/25519/ed25519.zig+21-13
...@@ -8,8 +8,15 @@ const crypto = std.crypto;...@@ -8,8 +8,15 @@ const crypto = std.crypto;
8const debug = std.debug;8const debug = std.debug;
9const fmt = std.fmt;9const fmt = std.fmt;
10const mem = std.mem;10const mem = std.mem;
11
11const Sha512 = crypto.hash.sha2.Sha512;12const Sha512 = crypto.hash.sha2.Sha512;
12const Error = crypto.Error;13
14const EncodingError = crypto.errors.EncodingError;
15const IdentityElementError = crypto.errors.IdentityElementError;
16const NonCanonicalError = crypto.errors.NonCanonicalError;
17const SignatureVerificationError = crypto.errors.SignatureVerificationError;
18const KeyMismatchError = crypto.errors.KeyMismatchError;
19const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1320
14/// Ed25519 (EdDSA) signatures.21/// Ed25519 (EdDSA) signatures.
15pub const Ed25519 = struct {22pub const Ed25519 = struct {
...@@ -41,7 +48,7 @@ pub const Ed25519 = struct {...@@ -41,7 +48,7 @@ pub const Ed25519 = struct {
41 ///48 ///
42 /// For this reason, an EdDSA secret key is commonly called a seed,49 /// For this reason, an EdDSA secret key is commonly called a seed,
43 /// from which the actual secret is derived.50 /// from which the actual secret is derived.
44 pub fn create(seed: ?[seed_length]u8) Error!KeyPair {51 pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
45 const ss = seed orelse ss: {52 const ss = seed orelse ss: {
46 var random_seed: [seed_length]u8 = undefined;53 var random_seed: [seed_length]u8 = undefined;
47 crypto.random.bytes(&random_seed);54 crypto.random.bytes(&random_seed);
...@@ -51,7 +58,7 @@ pub const Ed25519 = struct {...@@ -51,7 +58,7 @@ pub const Ed25519 = struct {
51 var h = Sha512.init(.{});58 var h = Sha512.init(.{});
52 h.update(&ss);59 h.update(&ss);
53 h.final(&az);60 h.final(&az);
54 const p = try Curve.basePoint.clampedMul(az[0..32].*);61 const p = Curve.basePoint.clampedMul(az[0..32].*) catch return error.IdentityElement;
55 var sk: [secret_length]u8 = undefined;62 var sk: [secret_length]u8 = undefined;
56 mem.copy(u8, &sk, &ss);63 mem.copy(u8, &sk, &ss);
57 const pk = p.toBytes();64 const pk = p.toBytes();
...@@ -72,7 +79,7 @@ pub const Ed25519 = struct {...@@ -72,7 +79,7 @@ pub const Ed25519 = struct {
72 /// Sign a message using a key pair, and optional random noise.79 /// Sign a message using a key pair, and optional random noise.
73 /// Having noise creates non-standard, non-deterministic signatures,80 /// Having noise creates non-standard, non-deterministic signatures,
74 /// but has been proven to increase resilience against fault attacks.81 /// but has been proven to increase resilience against fault attacks.
75 pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) Error![signature_length]u8 {82 pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) (IdentityElementError || WeakPublicKeyError || KeyMismatchError)![signature_length]u8 {
76 const seed = key_pair.secret_key[0..seed_length];83 const seed = key_pair.secret_key[0..seed_length];
77 const public_key = key_pair.secret_key[seed_length..];84 const public_key = key_pair.secret_key[seed_length..];
78 if (!mem.eql(u8, public_key, &key_pair.public_key)) {85 if (!mem.eql(u8, public_key, &key_pair.public_key)) {
...@@ -113,7 +120,7 @@ pub const Ed25519 = struct {...@@ -113,7 +120,7 @@ pub const Ed25519 = struct {
113120
114 /// Verify an Ed25519 signature given a message and a public key.121 /// Verify an Ed25519 signature given a message and a public key.
115 /// Returns error.SignatureVerificationFailed is the signature verification failed.122 /// Returns error.SignatureVerificationFailed is the signature verification failed.
116 pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) Error!void {123 pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) (SignatureVerificationError || WeakPublicKeyError || EncodingError || NonCanonicalError || IdentityElementError)!void {
117 const r = sig[0..32];124 const r = sig[0..32];
118 const s = sig[32..64];125 const s = sig[32..64];
119 try Curve.scalar.rejectNonCanonical(s.*);126 try Curve.scalar.rejectNonCanonical(s.*);
...@@ -122,6 +129,7 @@ pub const Ed25519 = struct {...@@ -122,6 +129,7 @@ pub const Ed25519 = struct {
122 try a.rejectIdentity();129 try a.rejectIdentity();
123 try Curve.rejectNonCanonical(r.*);130 try Curve.rejectNonCanonical(r.*);
124 const expected_r = try Curve.fromBytes(r.*);131 const expected_r = try Curve.fromBytes(r.*);
132 try expected_r.rejectIdentity();
125133
126 var h = Sha512.init(.{});134 var h = Sha512.init(.{});
127 h.update(r);135 h.update(r);
...@@ -131,8 +139,7 @@ pub const Ed25519 = struct {...@@ -131,8 +139,7 @@ pub const Ed25519 = struct {
131 h.final(&hram64);139 h.final(&hram64);
132 const hram = Curve.scalar.reduce64(hram64);140 const hram = Curve.scalar.reduce64(hram64);
133141
134 const ah = try a.neg().mulPublic(hram);142 const sb_ah = try Curve.basePoint.mulDoubleBasePublic(s.*, a.neg(), hram);
135 const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah);
136 if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| {143 if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| {
137 return error.SignatureVerificationFailed;144 return error.SignatureVerificationFailed;
138 } else |_| {}145 } else |_| {}
...@@ -146,7 +153,7 @@ pub const Ed25519 = struct {...@@ -146,7 +153,7 @@ pub const Ed25519 = struct {
146 };153 };
147154
148 /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one155 /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one
149 pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) Error!void {156 pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void {
150 var r_batch: [count][32]u8 = undefined;157 var r_batch: [count][32]u8 = undefined;
151 var s_batch: [count][32]u8 = undefined;158 var s_batch: [count][32]u8 = undefined;
152 var a_batch: [count]Curve = undefined;159 var a_batch: [count]Curve = undefined;
...@@ -161,6 +168,7 @@ pub const Ed25519 = struct {...@@ -161,6 +168,7 @@ pub const Ed25519 = struct {
161 try a.rejectIdentity();168 try a.rejectIdentity();
162 try Curve.rejectNonCanonical(r.*);169 try Curve.rejectNonCanonical(r.*);
163 const expected_r = try Curve.fromBytes(r.*);170 const expected_r = try Curve.fromBytes(r.*);
171 try expected_r.rejectIdentity();
164 expected_r_batch[i] = expected_r;172 expected_r_batch[i] = expected_r;
165 r_batch[i] = r.*;173 r_batch[i] = r.*;
166 s_batch[i] = s.*;174 s_batch[i] = s.*;
...@@ -180,7 +188,7 @@ pub const Ed25519 = struct {...@@ -180,7 +188,7 @@ pub const Ed25519 = struct {
180188
181 var z_batch: [count]Curve.scalar.CompressedScalar = undefined;189 var z_batch: [count]Curve.scalar.CompressedScalar = undefined;
182 for (z_batch) |*z| {190 for (z_batch) |*z| {
183 std.crypto.random.bytes(z[0..16]);191 crypto.random.bytes(z[0..16]);
184 mem.set(u8, z[16..], 0);192 mem.set(u8, z[16..], 0);
185 }193 }
186194
...@@ -233,8 +241,8 @@ test "ed25519 batch verification" {...@@ -233,8 +241,8 @@ test "ed25519 batch verification" {
233 const key_pair = try Ed25519.KeyPair.create(null);241 const key_pair = try Ed25519.KeyPair.create(null);
234 var msg1: [32]u8 = undefined;242 var msg1: [32]u8 = undefined;
235 var msg2: [32]u8 = undefined;243 var msg2: [32]u8 = undefined;
236 std.crypto.random.bytes(&msg1);244 crypto.random.bytes(&msg1);
237 std.crypto.random.bytes(&msg2);245 crypto.random.bytes(&msg2);
238 const sig1 = try Ed25519.sign(&msg1, key_pair, null);246 const sig1 = try Ed25519.sign(&msg1, key_pair, null);
239 const sig2 = try Ed25519.sign(&msg2, key_pair, null);247 const sig2 = try Ed25519.sign(&msg2, key_pair, null);
240 var signature_batch = [_]Ed25519.BatchElement{248 var signature_batch = [_]Ed25519.BatchElement{
...@@ -317,13 +325,13 @@ test "ed25519 test vectors" {...@@ -317,13 +325,13 @@ test "ed25519 test vectors" {
317 .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",325 .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",
318 .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",326 .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",
319 .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f",327 .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f",
320 .expected = error.SignatureVerificationFailed, // 8 - non-canonical R328 .expected = error.IdentityElement, // 8 - non-canonical R
321 },329 },
322 Vec{330 Vec{
323 .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",331 .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",
324 .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",332 .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",
325 .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908",333 .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908",
326 .expected = null, // 9 - non-canonical R334 .expected = error.IdentityElement, // 9 - non-canonical R
327 },335 },
328 Vec{336 Vec{
329 .msg_hex = "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b",337 .msg_hex = "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b",
lib/std/crypto/25519/edwards25519.zig+65-18
...@@ -4,10 +4,16 @@...@@ -4,10 +4,16 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const crypto = std.crypto;
7const debug = std.debug;8const debug = std.debug;
8const fmt = std.fmt;9const fmt = std.fmt;
9const mem = std.mem;10const mem = std.mem;
10const Error = std.crypto.Error;11
12const EncodingError = crypto.errors.EncodingError;
13const IdentityElementError = crypto.errors.IdentityElementError;
14const NonCanonicalError = crypto.errors.NonCanonicalError;
15const NotSquareError = crypto.errors.NotSquareError;
16const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1117
12/// Group operations over Edwards25519.18/// Group operations over Edwards25519.
13pub const Edwards25519 = struct {19pub const Edwards25519 = struct {
...@@ -26,7 +32,7 @@ pub const Edwards25519 = struct {...@@ -26,7 +32,7 @@ pub const Edwards25519 = struct {
26 is_base: bool = false,32 is_base: bool = false,
2733
28 /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.34 /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.
29 pub fn fromBytes(s: [encoded_length]u8) Error!Edwards25519 {35 pub fn fromBytes(s: [encoded_length]u8) EncodingError!Edwards25519 {
30 const z = Fe.one;36 const z = Fe.one;
31 const y = Fe.fromBytes(s);37 const y = Fe.fromBytes(s);
32 var u = y.sq();38 var u = y.sq();
...@@ -56,7 +62,7 @@ pub const Edwards25519 = struct {...@@ -56,7 +62,7 @@ pub const Edwards25519 = struct {
56 }62 }
5763
58 /// Check that the encoding of a point is canonical.64 /// Check that the encoding of a point is canonical.
59 pub fn rejectNonCanonical(s: [32]u8) Error!void {65 pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
60 return Fe.rejectNonCanonical(s, true);66 return Fe.rejectNonCanonical(s, true);
61 }67 }
6268
...@@ -81,7 +87,7 @@ pub const Edwards25519 = struct {...@@ -81,7 +87,7 @@ pub const Edwards25519 = struct {
81 const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };87 const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
8288
83 /// Reject the neutral element.89 /// Reject the neutral element.
84 pub fn rejectIdentity(p: Edwards25519) Error!void {90 pub fn rejectIdentity(p: Edwards25519) IdentityElementError!void {
85 if (p.x.isZero()) {91 if (p.x.isZero()) {
86 return error.IdentityElement;92 return error.IdentityElement;
87 }93 }
...@@ -177,7 +183,7 @@ pub const Edwards25519 = struct {...@@ -177,7 +183,7 @@ pub const Edwards25519 = struct {
177 // Based on real-world benchmarks, we only use this for multi-scalar multiplication.183 // Based on real-world benchmarks, we only use this for multi-scalar multiplication.
178 // NAF could be useful to half the size of precomputation tables, but we intentionally184 // NAF could be useful to half the size of precomputation tables, but we intentionally
179 // avoid these to keep the standard library lightweight.185 // avoid these to keep the standard library lightweight.
180 fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {186 fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
181 std.debug.assert(vartime);187 std.debug.assert(vartime);
182 const e = nonAdjacentForm(s);188 const e = nonAdjacentForm(s);
183 var q = Edwards25519.identityElement;189 var q = Edwards25519.identityElement;
...@@ -197,7 +203,7 @@ pub const Edwards25519 = struct {...@@ -197,7 +203,7 @@ pub const Edwards25519 = struct {
197 }203 }
198204
199 // Scalar multiplication with a 4-bit window and the first 15 multiples.205 // Scalar multiplication with a 4-bit window and the first 15 multiples.
200 fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {206 fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
201 var q = Edwards25519.identityElement;207 var q = Edwards25519.identityElement;
202 var pos: usize = 252;208 var pos: usize = 252;
203 while (true) : (pos -= 4) {209 while (true) : (pos -= 4) {
...@@ -232,10 +238,15 @@ pub const Edwards25519 = struct {...@@ -232,10 +238,15 @@ pub const Edwards25519 = struct {
232 break :pc precompute(Edwards25519.basePoint, 15);238 break :pc precompute(Edwards25519.basePoint, 15);
233 };239 };
234240
241 const basePointPc8 = comptime pc: {
242 @setEvalBranchQuota(10000);
243 break :pc precompute(Edwards25519.basePoint, 8);
244 };
245
235 /// Multiply an Edwards25519 point by a scalar without clamping it.246 /// Multiply an Edwards25519 point by a scalar without clamping it.
236 /// Return error.WeakPublicKey if the resulting point is247 /// Return error.WeakPublicKey if the base generates a small-order group,
237 /// the identity element.248 /// and error.IdentityElement if the result is the identity element.
238 pub fn mul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {249 pub fn mul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
239 const pc = if (p.is_base) basePointPc else pc: {250 const pc = if (p.is_base) basePointPc else pc: {
240 const xpc = precompute(p, 15);251 const xpc = precompute(p, 15);
241 xpc[4].rejectIdentity() catch return error.WeakPublicKey;252 xpc[4].rejectIdentity() catch return error.WeakPublicKey;
...@@ -246,7 +257,7 @@ pub const Edwards25519 = struct {...@@ -246,7 +257,7 @@ pub const Edwards25519 = struct {
246257
247 /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME*258 /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME*
248 /// This can be used for signature verification.259 /// This can be used for signature verification.
249 pub fn mulPublic(p: Edwards25519, s: [32]u8) Error!Edwards25519 {260 pub fn mulPublic(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
250 if (p.is_base) {261 if (p.is_base) {
251 return pcMul16(basePointPc, s, true);262 return pcMul16(basePointPc, s, true);
252 } else {263 } else {
...@@ -256,14 +267,50 @@ pub const Edwards25519 = struct {...@@ -256,14 +267,50 @@ pub const Edwards25519 = struct {
256 }267 }
257 }268 }
258269
270 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
271 /// This can be used for signature verification.
272 pub fn mulDoubleBasePublic(p1: Edwards25519, s1: [32]u8, p2: Edwards25519, s2: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
273 const pc1 = if (p1.is_base) basePointPc8 else pc: {
274 const xpc = precompute(p1, 8);
275 xpc[4].rejectIdentity() catch return error.WeakPublicKey;
276 break :pc xpc;
277 };
278 const pc2 = if (p2.is_base) basePointPc8 else pc: {
279 const xpc = precompute(p2, 8);
280 xpc[4].rejectIdentity() catch return error.WeakPublicKey;
281 break :pc xpc;
282 };
283 const e1 = nonAdjacentForm(s1);
284 const e2 = nonAdjacentForm(s2);
285 var q = Edwards25519.identityElement;
286 var pos: usize = 2 * 32 - 1;
287 while (true) : (pos -= 1) {
288 const slot1 = e1[pos];
289 if (slot1 > 0) {
290 q = q.add(pc1[@intCast(usize, slot1)]);
291 } else if (slot1 < 0) {
292 q = q.sub(pc1[@intCast(usize, -slot1)]);
293 }
294 const slot2 = e2[pos];
295 if (slot2 > 0) {
296 q = q.add(pc2[@intCast(usize, slot2)]);
297 } else if (slot2 < 0) {
298 q = q.sub(pc2[@intCast(usize, -slot2)]);
299 }
300 if (pos == 0) break;
301 q = q.dbl().dbl().dbl().dbl();
302 }
303 try q.rejectIdentity();
304 return q;
305 }
306
259 /// Multiscalar multiplication *IN VARIABLE TIME* for public data307 /// Multiscalar multiplication *IN VARIABLE TIME* for public data
260 /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually308 /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually
261 pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) Error!Edwards25519 {309 pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
262 var pcs: [count][9]Edwards25519 = undefined;310 var pcs: [count][9]Edwards25519 = undefined;
263 for (ps) |p, i| {311 for (ps) |p, i| {
264 if (p.is_base) {312 if (p.is_base) {
265 @setEvalBranchQuota(10000);313 pcs[i] = basePointPc8;
266 pcs[i] = comptime precompute(Edwards25519.basePoint, 8);
267 } else {314 } else {
268 pcs[i] = precompute(p, 8);315 pcs[i] = precompute(p, 8);
269 pcs[i][4].rejectIdentity() catch return error.WeakPublicKey;316 pcs[i][4].rejectIdentity() catch return error.WeakPublicKey;
...@@ -297,14 +344,14 @@ pub const Edwards25519 = struct {...@@ -297,14 +344,14 @@ pub const Edwards25519 = struct {
297 /// This is strongly recommended for DH operations.344 /// This is strongly recommended for DH operations.
298 /// Return error.WeakPublicKey if the resulting point is345 /// Return error.WeakPublicKey if the resulting point is
299 /// the identity element.346 /// the identity element.
300 pub fn clampedMul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {347 pub fn clampedMul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
301 var t: [32]u8 = s;348 var t: [32]u8 = s;
302 scalar.clamp(&t);349 scalar.clamp(&t);
303 return mul(p, t);350 return mul(p, t);
304 }351 }
305352
306 // montgomery -- recover y = sqrt(x^3 + A*x^2 + x)353 // montgomery -- recover y = sqrt(x^3 + A*x^2 + x)
307 fn xmontToYmont(x: Fe) Error!Fe {354 fn xmontToYmont(x: Fe) NotSquareError!Fe {
308 var x2 = x.sq();355 var x2 = x.sq();
309 const x3 = x.mul(x2);356 const x3 = x.mul(x2);
310 x2 = x2.mul32(Fe.edwards25519a_32);357 x2 = x2.mul32(Fe.edwards25519a_32);
...@@ -367,7 +414,7 @@ pub const Edwards25519 = struct {...@@ -367,7 +414,7 @@ pub const Edwards25519 = struct {
367414
368 fn stringToPoints(comptime n: usize, ctx: []const u8, s: []const u8) [n]Edwards25519 {415 fn stringToPoints(comptime n: usize, ctx: []const u8, s: []const u8) [n]Edwards25519 {
369 debug.assert(n <= 2);416 debug.assert(n <= 2);
370 const H = std.crypto.hash.sha2.Sha512;417 const H = crypto.hash.sha2.Sha512;
371 const h_l: usize = 48;418 const h_l: usize = 48;
372 var xctx = ctx;419 var xctx = ctx;
373 var hctx: [H.digest_length]u8 = undefined;420 var hctx: [H.digest_length]u8 = undefined;
...@@ -485,8 +532,8 @@ test "edwards25519 packing/unpacking" {...@@ -485,8 +532,8 @@ test "edwards25519 packing/unpacking" {
485test "edwards25519 point addition/substraction" {532test "edwards25519 point addition/substraction" {
486 var s1: [32]u8 = undefined;533 var s1: [32]u8 = undefined;
487 var s2: [32]u8 = undefined;534 var s2: [32]u8 = undefined;
488 std.crypto.random.bytes(&s1);535 crypto.random.bytes(&s1);
489 std.crypto.random.bytes(&s2);536 crypto.random.bytes(&s2);
490 const p = try Edwards25519.basePoint.clampedMul(s1);537 const p = try Edwards25519.basePoint.clampedMul(s1);
491 const q = try Edwards25519.basePoint.clampedMul(s2);538 const q = try Edwards25519.basePoint.clampedMul(s2);
492 const r = p.add(q).add(q).sub(q).sub(q);539 const r = p.add(q).add(q).sub(q).sub(q);
lib/std/crypto/25519/field.zig+6-3
...@@ -4,9 +4,12 @@...@@ -4,9 +4,12 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const crypto = std.crypto;
7const readIntLittle = std.mem.readIntLittle;8const readIntLittle = std.mem.readIntLittle;
8const writeIntLittle = std.mem.writeIntLittle;9const writeIntLittle = std.mem.writeIntLittle;
9const Error = std.crypto.Error;10
11const NonCanonicalError = crypto.errors.NonCanonicalError;
12const NotSquareError = crypto.errors.NotSquareError;
1013
11pub const Fe = struct {14pub const Fe = struct {
12 limbs: [5]u64,15 limbs: [5]u64,
...@@ -113,7 +116,7 @@ pub const Fe = struct {...@@ -113,7 +116,7 @@ pub const Fe = struct {
113 }116 }
114117
115 /// Reject non-canonical encodings of an element, possibly ignoring the top bit118 /// Reject non-canonical encodings of an element, possibly ignoring the top bit
116 pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) Error!void {119 pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) NonCanonicalError!void {
117 var c: u16 = (s[31] & 0x7f) ^ 0x7f;120 var c: u16 = (s[31] & 0x7f) ^ 0x7f;
118 comptime var i = 30;121 comptime var i = 30;
119 inline while (i > 0) : (i -= 1) {122 inline while (i > 0) : (i -= 1) {
...@@ -413,7 +416,7 @@ pub const Fe = struct {...@@ -413,7 +416,7 @@ pub const Fe = struct {
413 }416 }
414417
415 /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square418 /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square
416 pub fn sqrt(x2: Fe) Error!Fe {419 pub fn sqrt(x2: Fe) NotSquareError!Fe {
417 var x2_copy = x2;420 var x2_copy = x2;
418 const x = x2.uncheckedSqrt();421 const x = x2.uncheckedSqrt();
419 const check = x.sq().sub(x2_copy);422 const check = x.sq().sub(x2_copy);
lib/std/crypto/25519/ristretto255.zig+9-5
...@@ -5,7 +5,11 @@...@@ -5,7 +5,11 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const fmt = std.fmt;7const fmt = std.fmt;
8const Error = std.crypto.Error;8
9const EncodingError = std.crypto.errors.EncodingError;
10const IdentityElementError = std.crypto.errors.IdentityElementError;
11const NonCanonicalError = std.crypto.errors.NonCanonicalError;
12const WeakPublicKeyError = std.crypto.errors.WeakPublicKeyError;
913
10/// Group operations over Edwards25519.14/// Group operations over Edwards25519.
11pub const Ristretto255 = struct {15pub const Ristretto255 = struct {
...@@ -35,7 +39,7 @@ pub const Ristretto255 = struct {...@@ -35,7 +39,7 @@ pub const Ristretto255 = struct {
35 return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() };39 return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() };
36 }40 }
3741
38 fn rejectNonCanonical(s: [encoded_length]u8) Error!void {42 fn rejectNonCanonical(s: [encoded_length]u8) NonCanonicalError!void {
39 if ((s[0] & 1) != 0) {43 if ((s[0] & 1) != 0) {
40 return error.NonCanonical;44 return error.NonCanonical;
41 }45 }
...@@ -43,7 +47,7 @@ pub const Ristretto255 = struct {...@@ -43,7 +47,7 @@ pub const Ristretto255 = struct {
43 }47 }
4448
45 /// Reject the neutral element.49 /// Reject the neutral element.
46 pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) Error!void {50 pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) IdentityElementError!void {
47 return p.p.rejectIdentity();51 return p.p.rejectIdentity();
48 }52 }
4953
...@@ -51,7 +55,7 @@ pub const Ristretto255 = struct {...@@ -51,7 +55,7 @@ pub const Ristretto255 = struct {
51 pub const basePoint = Ristretto255{ .p = Curve.basePoint };55 pub const basePoint = Ristretto255{ .p = Curve.basePoint };
5256
53 /// Decode a Ristretto255 representative.57 /// Decode a Ristretto255 representative.
54 pub fn fromBytes(s: [encoded_length]u8) Error!Ristretto255 {58 pub fn fromBytes(s: [encoded_length]u8) (NonCanonicalError || EncodingError)!Ristretto255 {
55 try rejectNonCanonical(s);59 try rejectNonCanonical(s);
56 const s_ = Fe.fromBytes(s);60 const s_ = Fe.fromBytes(s);
57 const ss = s_.sq(); // s^261 const ss = s_.sq(); // s^2
...@@ -154,7 +158,7 @@ pub const Ristretto255 = struct {...@@ -154,7 +158,7 @@ pub const Ristretto255 = struct {
154 /// Multiply a Ristretto255 element with a scalar.158 /// Multiply a Ristretto255 element with a scalar.
155 /// Return error.WeakPublicKey if the resulting element is159 /// Return error.WeakPublicKey if the resulting element is
156 /// the identity element.160 /// the identity element.
157 pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) Error!Ristretto255 {161 pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) (IdentityElementError || WeakPublicKeyError)!Ristretto255 {
158 return Ristretto255{ .p = try p.p.mul(s) };162 return Ristretto255{ .p = try p.p.mul(s) };
159 }163 }
160164
lib/std/crypto/25519/scalar.zig+3-2
...@@ -5,7 +5,8 @@...@@ -5,7 +5,8 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const mem = std.mem;7const mem = std.mem;
8const Error = std.crypto.Error;8
9const NonCanonicalError = std.crypto.errors.NonCanonicalError;
910
10/// 2^252 + 2774231777737235353585193779088364849311/// 2^252 + 27742317777372353535851937790883648493
11pub const field_size = [32]u8{12pub const field_size = [32]u8{
...@@ -19,7 +20,7 @@ pub const CompressedScalar = [32]u8;...@@ -19,7 +20,7 @@ pub const CompressedScalar = [32]u8;
19pub const zero = [_]u8{0} ** 32;20pub const zero = [_]u8{0} ** 32;
2021
21/// Reject a scalar whose encoding is not canonical.22/// Reject a scalar whose encoding is not canonical.
22pub fn rejectNonCanonical(s: [32]u8) Error!void {23pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
23 var c: u8 = 0;24 var c: u8 = 0;
24 var n: u8 = 1;25 var n: u8 = 1;
25 var i: usize = 31;26 var i: usize = 31;
lib/std/crypto/25519/x25519.zig+9-6
...@@ -9,7 +9,10 @@ const mem = std.mem;...@@ -9,7 +9,10 @@ const mem = std.mem;
9const fmt = std.fmt;9const fmt = std.fmt;
1010
11const Sha512 = crypto.hash.sha2.Sha512;11const Sha512 = crypto.hash.sha2.Sha512;
12const Error = crypto.Error;12
13const EncodingError = crypto.errors.EncodingError;
14const IdentityElementError = crypto.errors.IdentityElementError;
15const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1316
14/// X25519 DH function.17/// X25519 DH function.
15pub const X25519 = struct {18pub const X25519 = struct {
...@@ -32,7 +35,7 @@ pub const X25519 = struct {...@@ -32,7 +35,7 @@ pub const X25519 = struct {
32 secret_key: [secret_length]u8,35 secret_key: [secret_length]u8,
3336
34 /// Create a new key pair using an optional seed.37 /// Create a new key pair using an optional seed.
35 pub fn create(seed: ?[seed_length]u8) Error!KeyPair {38 pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
36 const sk = seed orelse sk: {39 const sk = seed orelse sk: {
37 var random_seed: [seed_length]u8 = undefined;40 var random_seed: [seed_length]u8 = undefined;
38 crypto.random.bytes(&random_seed);41 crypto.random.bytes(&random_seed);
...@@ -45,7 +48,7 @@ pub const X25519 = struct {...@@ -45,7 +48,7 @@ pub const X25519 = struct {
45 }48 }
4649
47 /// Create a key pair from an Ed25519 key pair50 /// Create a key pair from an Ed25519 key pair
48 pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) Error!KeyPair {51 pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) (IdentityElementError || EncodingError)!KeyPair {
49 const seed = ed25519_key_pair.secret_key[0..32];52 const seed = ed25519_key_pair.secret_key[0..32];
50 var az: [Sha512.digest_length]u8 = undefined;53 var az: [Sha512.digest_length]u8 = undefined;
51 Sha512.hash(seed, &az, .{});54 Sha512.hash(seed, &az, .{});
...@@ -60,13 +63,13 @@ pub const X25519 = struct {...@@ -60,13 +63,13 @@ pub const X25519 = struct {
60 };63 };
6164
62 /// Compute the public key for a given private key.65 /// Compute the public key for a given private key.
63 pub fn recoverPublicKey(secret_key: [secret_length]u8) Error![public_length]u8 {66 pub fn recoverPublicKey(secret_key: [secret_length]u8) IdentityElementError![public_length]u8 {
64 const q = try Curve.basePoint.clampedMul(secret_key);67 const q = try Curve.basePoint.clampedMul(secret_key);
65 return q.toBytes();68 return q.toBytes();
66 }69 }
6770
68 /// Compute the X25519 equivalent to an Ed25519 public eky.71 /// Compute the X25519 equivalent to an Ed25519 public eky.
69 pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) Error![public_length]u8 {72 pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) (IdentityElementError || EncodingError)![public_length]u8 {
70 const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key);73 const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key);
71 const pk = try Curve.fromEdwards25519(pk_ed);74 const pk = try Curve.fromEdwards25519(pk_ed);
72 return pk.toBytes();75 return pk.toBytes();
...@@ -75,7 +78,7 @@ pub const X25519 = struct {...@@ -75,7 +78,7 @@ pub const X25519 = struct {
75 /// Compute the scalar product of a public key and a secret scalar.78 /// Compute the scalar product of a public key and a secret scalar.
76 /// Note that the output should not be used as a shared secret without79 /// Note that the output should not be used as a shared secret without
77 /// hashing it first.80 /// hashing it first.
78 pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) Error![shared_length]u8 {81 pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) IdentityElementError![shared_length]u8 {
79 const q = try Curve.fromBytes(public_key).clampedMul(secret_key);82 const q = try Curve.fromBytes(public_key).clampedMul(secret_key);
80 return q.toBytes();83 return q.toBytes();
81 }84 }
lib/std/crypto/aegis.zig+3-3
...@@ -8,7 +8,7 @@ const std = @import("std");...@@ -8,7 +8,7 @@ const std = @import("std");
8const mem = std.mem;8const mem = std.mem;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const AesBlock = std.crypto.core.aes.Block;10const AesBlock = std.crypto.core.aes.Block;
11const Error = std.crypto.Error;11const AuthenticationError = std.crypto.errors.AuthenticationError;
1212
13const State128L = struct {13const State128L = struct {
14 blocks: [8]AesBlock,14 blocks: [8]AesBlock,
...@@ -137,7 +137,7 @@ pub const Aegis128L = struct {...@@ -137,7 +137,7 @@ pub const Aegis128L = struct {
137 /// ad: Associated Data137 /// ad: Associated Data
138 /// npub: public nonce138 /// npub: public nonce
139 /// k: private key139 /// k: private key
140 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {140 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
141 assert(c.len == m.len);141 assert(c.len == m.len);
142 var state = State128L.init(key, npub);142 var state = State128L.init(key, npub);
143 var src: [32]u8 align(16) = undefined;143 var src: [32]u8 align(16) = undefined;
...@@ -299,7 +299,7 @@ pub const Aegis256 = struct {...@@ -299,7 +299,7 @@ pub const Aegis256 = struct {
299 /// ad: Associated Data299 /// ad: Associated Data
300 /// npub: public nonce300 /// npub: public nonce
301 /// k: private key301 /// k: private key
302 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {302 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
303 assert(c.len == m.len);303 assert(c.len == m.len);
304 var state = State256.init(key, npub);304 var state = State256.init(key, npub);
305 var src: [16]u8 align(16) = undefined;305 var src: [16]u8 align(16) = undefined;
lib/std/crypto/aes_gcm.zig+2-2
...@@ -12,7 +12,7 @@ const debug = std.debug;...@@ -12,7 +12,7 @@ const debug = std.debug;
12const Ghash = std.crypto.onetimeauth.Ghash;12const Ghash = std.crypto.onetimeauth.Ghash;
13const mem = std.mem;13const mem = std.mem;
14const modes = crypto.core.modes;14const modes = crypto.core.modes;
15const Error = crypto.Error;15const AuthenticationError = crypto.errors.AuthenticationError;
1616
17pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128);17pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128);
18pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256);18pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256);
...@@ -60,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type {...@@ -60,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type {
60 }60 }
61 }61 }
6262
63 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {63 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
64 assert(c.len == m.len);64 assert(c.len == m.len);
6565
66 const aes = Aes.initEnc(key);66 const aes = Aes.initEnc(key);
lib/std/crypto/aes_ocb.zig+2-2
...@@ -10,7 +10,7 @@ const aes = crypto.core.aes;...@@ -10,7 +10,7 @@ const aes = crypto.core.aes;
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const math = std.math;11const math = std.math;
12const mem = std.mem;12const mem = std.mem;
13const Error = crypto.Error;13const AuthenticationError = crypto.errors.AuthenticationError;
1414
15pub const Aes128Ocb = AesOcb(aes.Aes128);15pub const Aes128Ocb = AesOcb(aes.Aes128);
16pub const Aes256Ocb = AesOcb(aes.Aes256);16pub const Aes256Ocb = AesOcb(aes.Aes256);
...@@ -179,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type {...@@ -179,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type {
179 /// ad: Associated Data179 /// ad: Associated Data
180 /// npub: public nonce180 /// npub: public nonce
181 /// k: secret key181 /// k: secret key
182 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {182 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
183 assert(c.len == m.len);183 assert(c.len == m.len);
184184
185 const aes_enc_ctx = Aes.initEnc(key);185 const aes_enc_ctx = Aes.initEnc(key);
lib/std/crypto/bcrypt.zig+6-5
...@@ -12,7 +12,8 @@ const mem = std.mem;...@@ -12,7 +12,8 @@ const mem = std.mem;
12const debug = std.debug;12const debug = std.debug;
13const testing = std.testing;13const testing = std.testing;
14const utils = crypto.utils;14const utils = crypto.utils;
15const Error = crypto.Error;15const EncodingError = crypto.errors.EncodingError;
16const PasswordVerificationError = crypto.errors.PasswordVerificationError;
1617
17const salt_length: usize = 16;18const salt_length: usize = 16;
18const salt_str_length: usize = 22;19const salt_str_length: usize = 22;
...@@ -179,7 +180,7 @@ const Codec = struct {...@@ -179,7 +180,7 @@ const Codec = struct {
179 debug.assert(j == b64.len);180 debug.assert(j == b64.len);
180 }181 }
181182
182 fn decode(bin: []u8, b64: []const u8) Error!void {183 fn decode(bin: []u8, b64: []const u8) EncodingError!void {
183 var i: usize = 0;184 var i: usize = 0;
184 var j: usize = 0;185 var j: usize = 0;
185 while (j < bin.len) {186 while (j < bin.len) {
...@@ -204,7 +205,7 @@ const Codec = struct {...@@ -204,7 +205,7 @@ const Codec = struct {
204 }205 }
205};206};
206207
207fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) Error![hash_length]u8 {208fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) ![hash_length]u8 {
208 var state = State{};209 var state = State{};
209 var password_buf: [73]u8 = undefined;210 var password_buf: [73]u8 = undefined;
210 const trimmed_len = math.min(password.len, password_buf.len - 1);211 const trimmed_len = math.min(password.len, password_buf.len - 1);
...@@ -252,14 +253,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8)...@@ -252,14 +253,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8)
252/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes.253/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes.
253/// If this is an issue for your application, hash the password first using a function such as SHA-512,254/// If this is an issue for your application, hash the password first using a function such as SHA-512,
254/// and then use the resulting hash as the password parameter for bcrypt.255/// and then use the resulting hash as the password parameter for bcrypt.
255pub fn strHash(password: []const u8, rounds_log: u6) Error![hash_length]u8 {256pub fn strHash(password: []const u8, rounds_log: u6) ![hash_length]u8 {
256 var salt: [salt_length]u8 = undefined;257 var salt: [salt_length]u8 = undefined;
257 crypto.random.bytes(&salt);258 crypto.random.bytes(&salt);
258 return strHashInternal(password, rounds_log, salt);259 return strHashInternal(password, rounds_log, salt);
259}260}
260261
261/// Verify that a previously computed hash is valid for a given password.262/// Verify that a previously computed hash is valid for a given password.
262pub fn strVerify(h: [hash_length]u8, password: []const u8) Error!void {263pub fn strVerify(h: [hash_length]u8, password: []const u8) (EncodingError || PasswordVerificationError)!void {
263 if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding;264 if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding;
264 if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding;265 if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding;
265 const rounds_log_str = h[4..][0..2];266 const rounds_log_str = h[4..][0..2];
lib/std/crypto/chacha20.zig+3-3
...@@ -13,7 +13,7 @@ const testing = std.testing;...@@ -13,7 +13,7 @@ const testing = std.testing;
13const maxInt = math.maxInt;13const maxInt = math.maxInt;
14const Vector = std.meta.Vector;14const Vector = std.meta.Vector;
15const Poly1305 = std.crypto.onetimeauth.Poly1305;15const Poly1305 = std.crypto.onetimeauth.Poly1305;
16const Error = std.crypto.Error;16const AuthenticationError = std.crypto.errors.AuthenticationError;
1717
18/// IETF-variant of the ChaCha20 stream cipher, as designed for TLS.18/// IETF-variant of the ChaCha20 stream cipher, as designed for TLS.
19pub const ChaCha20IETF = ChaChaIETF(20);19pub const ChaCha20IETF = ChaChaIETF(20);
...@@ -521,7 +521,7 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type {...@@ -521,7 +521,7 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type {
521 /// npub: public nonce521 /// npub: public nonce
522 /// k: private key522 /// k: private key
523 /// NOTE: the check of the authentication tag is currently not done in constant time523 /// NOTE: the check of the authentication tag is currently not done in constant time
524 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {524 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
525 assert(c.len == m.len);525 assert(c.len == m.len);
526526
527 var polyKey = [_]u8{0} ** 32;527 var polyKey = [_]u8{0} ** 32;
...@@ -583,7 +583,7 @@ fn XChaChaPoly1305(comptime rounds_nb: usize) type {...@@ -583,7 +583,7 @@ fn XChaChaPoly1305(comptime rounds_nb: usize) type {
583 /// ad: Associated Data583 /// ad: Associated Data
584 /// npub: public nonce584 /// npub: public nonce
585 /// k: private key585 /// k: private key
586 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {586 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
587 const extended = extend(k, npub, rounds_nb);587 const extended = extend(k, npub, rounds_nb);
588 return ChaChaPoly1305(rounds_nb).decrypt(m, c, tag, ad, extended.nonce, extended.key);588 return ChaChaPoly1305(rounds_nb).decrypt(m, c, tag, ad, extended.nonce, extended.key);
589 }589 }
lib/std/crypto/error.zig deleted-34
...@@ -1,34 +0,0 @@
1pub const Error = error{
2 /// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
3 AuthenticationFailed,
4
5 /// The requested output length is too long for the chosen algorithm
6 OutputTooLong,
7
8 /// Finite field operation returned the identity element
9 IdentityElement,
10
11 /// Encoded input cannot be decoded
12 InvalidEncoding,
13
14 /// The signature does't verify for the given message and public key
15 SignatureVerificationFailed,
16
17 /// Both a public and secret key have been provided, but they are incompatible
18 KeyMismatch,
19
20 /// Encoded input is not in canonical form
21 NonCanonical,
22
23 /// Square root has no solutions
24 NotSquare,
25
26 /// Verification string doesn't match the provided password and parameters
27 PasswordVerificationFailed,
28
29 /// Parameters would be insecure to use
30 WeakParameters,
31
32 /// Public key would be insecure to use
33 WeakPublicKey,
34};
lib/std/crypto/errors.zig created+35
...@@ -0,0 +1,35 @@
1/// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
2pub const AuthenticationError = error{AuthenticationFailed};
3
4/// The requested output length is too long for the chosen algorithm
5pub const OutputTooLongError = error{OutputTooLong};
6
7/// Finite field operation returned the identity element
8pub const IdentityElementError = error{IdentityElement};
9
10/// Encoded input cannot be decoded
11pub const EncodingError = error{InvalidEncoding};
12
13/// The signature does't verify for the given message and public key
14pub const SignatureVerificationError = error{SignatureVerificationFailed};
15
16/// Both a public and secret key have been provided, but they are incompatible
17pub const KeyMismatchError = error{KeyMismatch};
18
19/// Encoded input is not in canonical form
20pub const NonCanonicalError = error{NonCanonical};
21
22/// Square root has no solutions
23pub const NotSquareError = error{NotSquare};
24
25/// Verification string doesn't match the provided password and parameters
26pub const PasswordVerificationError = error{PasswordVerificationFailed};
27
28/// Parameters would be insecure to use
29pub const WeakParametersError = error{WeakParameters};
30
31/// Public key would be insecure to use
32pub const WeakPublicKeyError = error{WeakPublicKey};
33
34/// Any error related to cryptography operations
35pub const Error = AuthenticationError || OutputTooLongError || IdentityElementError || EncodingError || SignatureVerificationError || KeyMismatchError || NonCanonicalError || NotSquareError || PasswordVerificationError || WeakParametersError || WeakPublicKeyError;
lib/std/crypto/gimli.zig+2-2
...@@ -20,7 +20,7 @@ const assert = std.debug.assert;...@@ -20,7 +20,7 @@ const assert = std.debug.assert;
20const testing = std.testing;20const testing = std.testing;
21const htest = @import("test.zig");21const htest = @import("test.zig");
22const Vector = std.meta.Vector;22const Vector = std.meta.Vector;
23const Error = std.crypto.Error;23const AuthenticationError = std.crypto.errors.AuthenticationError;
2424
25pub const State = struct {25pub const State = struct {
26 pub const BLOCKBYTES = 48;26 pub const BLOCKBYTES = 48;
...@@ -393,7 +393,7 @@ pub const Aead = struct {...@@ -393,7 +393,7 @@ pub const Aead = struct {
393 /// npub: public nonce393 /// npub: public nonce
394 /// k: private key394 /// k: private key
395 /// NOTE: the check of the authentication tag is currently not done in constant time395 /// NOTE: the check of the authentication tag is currently not done in constant time
396 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {396 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
397 assert(c.len == m.len);397 assert(c.len == m.len);
398398
399 var state = Aead.init(ad, npub, k);399 var state = Aead.init(ad, npub, k);
lib/std/crypto/isap.zig+2-2
...@@ -3,7 +3,7 @@ const debug = std.debug;...@@ -3,7 +3,7 @@ const debug = std.debug;
3const mem = std.mem;3const mem = std.mem;
4const math = std.math;4const math = std.math;
5const testing = std.testing;5const testing = std.testing;
6const Error = std.crypto.Error;6const AuthenticationError = std.crypto.errors.AuthenticationError;
77
8/// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks.8/// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks.
9/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf9/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf
...@@ -218,7 +218,7 @@ pub const IsapA128A = struct {...@@ -218,7 +218,7 @@ pub const IsapA128A = struct {
218 tag.* = mac(c, ad, npub, key);218 tag.* = mac(c, ad, npub, key);
219 }219 }
220220
221 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {221 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
222 var computed_tag = mac(c, ad, npub, key);222 var computed_tag = mac(c, ad, npub, key);
223 var acc: u8 = 0;223 var acc: u8 = 0;
224 for (computed_tag) |_, j| {224 for (computed_tag) |_, j| {
lib/std/crypto/pbkdf2.zig+3-2
...@@ -7,7 +7,8 @@...@@ -7,7 +7,8 @@
7const std = @import("std");7const std = @import("std");
8const mem = std.mem;8const mem = std.mem;
9const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
10const Error = std.crypto.Error;10const OutputTooLongError = std.crypto.errors.OutputTooLongError;
11const WeakParametersError = std.crypto.errors.WeakParametersError;
1112
12// RFC 2898 Section 5.213// RFC 2898 Section 5.2
13//14//
...@@ -55,7 +56,7 @@ const Error = std.crypto.Error;...@@ -55,7 +56,7 @@ const Error = std.crypto.Error;
55/// the dk. It is common to tune this parameter to achieve approximately 100ms.56/// the dk. It is common to tune this parameter to achieve approximately 100ms.
56///57///
57/// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`.58/// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`.
58pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Error!void {59pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) (WeakParametersError || OutputTooLongError)!void {
59 if (rounds < 1) return error.WeakParameters;60 if (rounds < 1) return error.WeakParameters;
6061
61 const dk_len = dk.len;62 const dk_len = dk.len;
lib/std/crypto/salsa20.zig+11-8
...@@ -15,7 +15,10 @@ const Vector = std.meta.Vector;...@@ -15,7 +15,10 @@ const Vector = std.meta.Vector;
15const Poly1305 = crypto.onetimeauth.Poly1305;15const Poly1305 = crypto.onetimeauth.Poly1305;
16const Blake2b = crypto.hash.blake2.Blake2b;16const Blake2b = crypto.hash.blake2.Blake2b;
17const X25519 = crypto.dh.X25519;17const X25519 = crypto.dh.X25519;
18const Error = crypto.Error;18
19const AuthenticationError = crypto.errors.AuthenticationError;
20const IdentityElementError = crypto.errors.IdentityElementError;
21const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1922
20const Salsa20VecImpl = struct {23const Salsa20VecImpl = struct {
21 const Lane = Vector(4, u32);24 const Lane = Vector(4, u32);
...@@ -399,7 +402,7 @@ pub const XSalsa20Poly1305 = struct {...@@ -399,7 +402,7 @@ pub const XSalsa20Poly1305 = struct {
399 /// ad: Associated Data402 /// ad: Associated Data
400 /// npub: public nonce403 /// npub: public nonce
401 /// k: private key404 /// k: private key
402 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {405 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
403 debug.assert(c.len == m.len);406 debug.assert(c.len == m.len);
404 const extended = extend(k, npub);407 const extended = extend(k, npub);
405 var block0 = [_]u8{0} ** 64;408 var block0 = [_]u8{0} ** 64;
...@@ -447,7 +450,7 @@ pub const SecretBox = struct {...@@ -447,7 +450,7 @@ pub const SecretBox = struct {
447450
448 /// Verify and decrypt `c` using a nonce `npub` and a key `k`.451 /// Verify and decrypt `c` using a nonce `npub` and a key `k`.
449 /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message.452 /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message.
450 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {453 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
451 if (c.len < tag_length) {454 if (c.len < tag_length) {
452 return error.AuthenticationFailed;455 return error.AuthenticationFailed;
453 }456 }
...@@ -482,20 +485,20 @@ pub const Box = struct {...@@ -482,20 +485,20 @@ pub const Box = struct {
482 pub const KeyPair = X25519.KeyPair;485 pub const KeyPair = X25519.KeyPair;
483486
484 /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key.487 /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key.
485 pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) Error![shared_length]u8 {488 pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)![shared_length]u8 {
486 const p = try X25519.scalarmult(secret_key, public_key);489 const p = try X25519.scalarmult(secret_key, public_key);
487 const zero = [_]u8{0} ** 16;490 const zero = [_]u8{0} ** 16;
488 return Salsa20Impl.hsalsa20(zero, p);491 return Salsa20Impl.hsalsa20(zero, p);
489 }492 }
490493
491 /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`.494 /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`.
492 pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {495 pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)!void {
493 const shared_key = try createSharedSecret(public_key, secret_key);496 const shared_key = try createSharedSecret(public_key, secret_key);
494 return SecretBox.seal(c, m, npub, shared_key);497 return SecretBox.seal(c, m, npub, shared_key);
495 }498 }
496499
497 /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`.500 /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`.
498 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {501 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
499 const shared_key = try createSharedSecret(public_key, secret_key);502 const shared_key = try createSharedSecret(public_key, secret_key);
500 return SecretBox.open(m, c, npub, shared_key);503 return SecretBox.open(m, c, npub, shared_key);
501 }504 }
...@@ -528,7 +531,7 @@ pub const SealedBox = struct {...@@ -528,7 +531,7 @@ pub const SealedBox = struct {
528531
529 /// Encrypt a message `m` for a recipient whose public key is `public_key`.532 /// Encrypt a message `m` for a recipient whose public key is `public_key`.
530 /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added.533 /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added.
531 pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) Error!void {534 pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void {
532 debug.assert(c.len == m.len + seal_length);535 debug.assert(c.len == m.len + seal_length);
533 var ekp = try KeyPair.create(null);536 var ekp = try KeyPair.create(null);
534 const nonce = createNonce(ekp.public_key, public_key);537 const nonce = createNonce(ekp.public_key, public_key);
...@@ -539,7 +542,7 @@ pub const SealedBox = struct {...@@ -539,7 +542,7 @@ pub const SealedBox = struct {
539542
540 /// Decrypt a message using a key pair.543 /// Decrypt a message using a key pair.
541 /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata.544 /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata.
542 pub fn open(m: []u8, c: []const u8, keypair: KeyPair) Error!void {545 pub fn open(m: []u8, c: []const u8, keypair: KeyPair) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
543 if (c.len < seal_length) {546 if (c.len < seal_length) {
544 return error.AuthenticationFailed;547 return error.AuthenticationFailed;
545 }548 }
lib/std/event/rwlock.zig+2-2
...@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;...@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;
264var shared_test_index: usize = 0;264var shared_test_index: usize = 0;
265var shared_count: usize = 0;265var shared_count: usize = 0;
266fn writeRunner(lock: *RwLock) callconv(.Async) void {266fn writeRunner(lock: *RwLock) callconv(.Async) void {
267 suspend; // resumed by onNextTick267 suspend {} // resumed by onNextTick
268268
269 var i: usize = 0;269 var i: usize = 0;
270 while (i < shared_test_data.len) : (i += 1) {270 while (i < shared_test_data.len) : (i += 1) {
...@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {...@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {
281 }281 }
282}282}
283fn readRunner(lock: *RwLock) callconv(.Async) void {283fn readRunner(lock: *RwLock) callconv(.Async) void {
284 suspend; // resumed by onNextTick284 suspend {} // resumed by onNextTick
285 std.time.sleep(1);285 std.time.sleep(1);
286286
287 var i: usize = 0;287 var i: usize = 0;
lib/std/math.zig-9
...@@ -1349,15 +1349,6 @@ pub fn boolMask(comptime MaskInt: type, value: bool) callconv(.Inline) MaskInt {...@@ -1349,15 +1349,6 @@ pub fn boolMask(comptime MaskInt: type, value: bool) callconv(.Inline) MaskInt {
1349 return @bitCast(i1, @as(u1, @boolToInt(value)));1349 return @bitCast(i1, @as(u1, @boolToInt(value)));
1350 }1350 }
13511351
1352 // At comptime, -% is disallowed on unsigned values.
1353 // So we need to jump through some hoops in that case.
1354 // This is a workaround for #7951
1355 if (@typeInfo(@TypeOf(.{value})).Struct.fields[0].is_comptime) {
1356 // Since it's comptime, we don't need this to generate nice code.
1357 // We can just do a branch here.
1358 return if (value) ~@as(MaskInt, 0) else 0;
1359 }
1360
1361 return -%@intCast(MaskInt, @boolToInt(value));1352 return -%@intCast(MaskInt, @boolToInt(value));
1362}1353}
13631354
lib/std/math/sqrt.zig+17-3
...@@ -38,7 +38,13 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {...@@ -38,7 +38,13 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {
38 }38 }
39}39}
4040
41fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int.bits / 2) {41fn sqrt_int(comptime T: type, value: T) Sqrt(T) {
42 switch (T) {
43 u0 => return 0,
44 u1 => return value,
45 else => {},
46 }
47
42 var op = value;48 var op = value;
43 var res: T = 0;49 var res: T = 0;
44 var one: T = 1 << (@typeInfo(T).Int.bits - 2);50 var one: T = 1 << (@typeInfo(T).Int.bits - 2);
...@@ -57,11 +63,13 @@ fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int...@@ -57,11 +63,13 @@ fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int
57 one >>= 2;63 one >>= 2;
58 }64 }
5965
60 const ResultType = std.meta.Int(.unsigned, @typeInfo(T).Int.bits / 2);66 const ResultType = Sqrt(T);
61 return @intCast(ResultType, res);67 return @intCast(ResultType, res);
62}68}
6369
64test "math.sqrt_int" {70test "math.sqrt_int" {
71 expect(sqrt_int(u0, 0) == 0);
72 expect(sqrt_int(u1, 1) == 1);
65 expect(sqrt_int(u32, 3) == 1);73 expect(sqrt_int(u32, 3) == 1);
66 expect(sqrt_int(u32, 4) == 2);74 expect(sqrt_int(u32, 4) == 2);
67 expect(sqrt_int(u32, 5) == 2);75 expect(sqrt_int(u32, 5) == 2);
...@@ -73,7 +81,13 @@ test "math.sqrt_int" {...@@ -73,7 +81,13 @@ test "math.sqrt_int" {
73/// Returns the return type `sqrt` will return given an operand of type `T`.81/// Returns the return type `sqrt` will return given an operand of type `T`.
74pub fn Sqrt(comptime T: type) type {82pub fn Sqrt(comptime T: type) type {
75 return switch (@typeInfo(T)) {83 return switch (@typeInfo(T)) {
76 .Int => |int| std.meta.Int(.unsigned, int.bits / 2),84 .Int => |int| {
85 return switch (int.bits) {
86 0 => u0,
87 1 => u1,
88 else => std.meta.Int(.unsigned, int.bits / 2),
89 };
90 },
77 else => T,91 else => T,
78 };92 };
79}93}
lib/std/meta.zig+15-3
...@@ -884,7 +884,7 @@ pub fn Vector(comptime len: u32, comptime child: type) type {...@@ -884,7 +884,7 @@ pub fn Vector(comptime len: u32, comptime child: type) type {
884/// Given a type and value, cast the value to the type as c would.884/// Given a type and value, cast the value to the type as c would.
885/// This is for translate-c and is not intended for general use.885/// This is for translate-c and is not intended for general use.
886pub fn cast(comptime DestType: type, target: anytype) DestType {886pub fn cast(comptime DestType: type, target: anytype) DestType {
887 // this function should behave like transCCast in translate-c, except it's for macros887 // this function should behave like transCCast in translate-c, except it's for macros and enums
888 const SourceType = @TypeOf(target);888 const SourceType = @TypeOf(target);
889 switch (@typeInfo(DestType)) {889 switch (@typeInfo(DestType)) {
890 .Pointer => {890 .Pointer => {
...@@ -921,9 +921,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {...@@ -921,9 +921,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
921 }921 }
922 }922 }
923 },923 },
924 .Enum => {924 .Enum => |enum_type| {
925 if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) {925 if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) {
926 return @intToEnum(DestType, target);926 const intermediate = cast(enum_type.tag_type, target);
927 return @intToEnum(DestType, intermediate);
927 }928 }
928 },929 },
929 .Int => {930 .Int => {
...@@ -1011,6 +1012,17 @@ test "std.meta.cast" {...@@ -1011,6 +1012,17 @@ test "std.meta.cast" {
1011 testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*volatile u8, 2)));1012 testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*volatile u8, 2)));
10121013
1013 testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));1014 testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));
1015
1016 const C_ENUM = extern enum(c_int) {
1017 A = 0,
1018 B,
1019 C,
1020 _,
1021 };
1022 testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1));
1023 testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);
1024 testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);
1025 testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));
1014}1026}
10151027
1016/// Given a value returns its size as C's sizeof operator would.1028/// Given a value returns its size as C's sizeof operator would.
lib/std/os/bits/linux/powerpc.zig+1-9
...@@ -557,18 +557,10 @@ pub const kernel_stat = extern struct {...@@ -557,18 +557,10 @@ pub const kernel_stat = extern struct {
557 size: off_t,557 size: off_t,
558 blksize: blksize_t,558 blksize: blksize_t,
559 blocks: blkcnt_t,559 blocks: blkcnt_t,
560 __atim32: timespec32,
561 __mtim32: timespec32,
562 __ctim32: timespec32,
563 __unused: [2]u32,
564 atim: timespec,560 atim: timespec,
565 mtim: timespec,561 mtim: timespec,
566 ctim: timespec,562 ctim: timespec,
567563 __unused: [2]u32,
568 const timespec32 = extern struct {
569 tv_sec: i32,
570 tv_nsec: i32,
571 };
572564
573 pub fn atime(self: @This()) timespec {565 pub fn atime(self: @This()) timespec {
574 return self.atim;566 return self.atim;
lib/std/os/linux.zig+49-1
...@@ -53,6 +53,7 @@ pub fn getauxval(index: usize) usize {...@@ -53,6 +53,7 @@ pub fn getauxval(index: usize) usize {
53// Some architectures (and some syscalls) require 64bit parameters to be passed53// Some architectures (and some syscalls) require 64bit parameters to be passed
54// in a even-aligned register pair.54// in a even-aligned register pair.
55const require_aligned_register_pair =55const require_aligned_register_pair =
56 std.Target.current.cpu.arch.isPPC() or
56 std.Target.current.cpu.arch.isMIPS() or57 std.Target.current.cpu.arch.isMIPS() or
57 std.Target.current.cpu.arch.isARM() or58 std.Target.current.cpu.arch.isARM() or
58 std.Target.current.cpu.arch.isThumb();59 std.Target.current.cpu.arch.isThumb();
...@@ -633,7 +634,7 @@ pub fn tkill(tid: pid_t, sig: i32) usize {...@@ -633,7 +634,7 @@ pub fn tkill(tid: pid_t, sig: i32) usize {
633}634}
634635
635pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize {636pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize {
636 return syscall2(.tgkill, @bitCast(usize, @as(isize, tgid)), @bitCast(usize, @as(isize, tid)), @bitCast(usize, @as(isize, sig)));637 return syscall3(.tgkill, @bitCast(usize, @as(isize, tgid)), @bitCast(usize, @as(isize, tid)), @bitCast(usize, @as(isize, sig)));
637}638}
638639
639pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {640pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {
...@@ -1386,6 +1387,53 @@ pub fn madvise(address: [*]u8, len: usize, advice: u32) usize {...@@ -1386,6 +1387,53 @@ pub fn madvise(address: [*]u8, len: usize, advice: u32) usize {
1386 return syscall3(.madvise, @ptrToInt(address), len, advice);1387 return syscall3(.madvise, @ptrToInt(address), len, advice);
1387}1388}
13881389
1390pub fn pidfd_open(pid: pid_t, flags: u32) usize {
1391 return syscall2(.pidfd_open, @bitCast(usize, @as(isize, pid)), flags);
1392}
1393
1394pub fn pidfd_getfd(pidfd: fd_t, targetfd: fd_t, flags: u32) usize {
1395 return syscall3(
1396 .pidfd_getfd,
1397 @bitCast(usize, @as(isize, pidfd)),
1398 @bitCast(usize, @as(isize, targetfd)),
1399 flags,
1400 );
1401}
1402
1403pub fn pidfd_send_signal(pidfd: fd_t, sig: i32, info: ?*siginfo_t, flags: u32) usize {
1404 return syscall4(
1405 .pidfd_send_signal,
1406 @bitCast(usize, @as(isize, pidfd)),
1407 @bitCast(usize, @as(isize, sig)),
1408 @ptrToInt(info),
1409 flags,
1410 );
1411}
1412
1413pub fn process_vm_readv(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
1414 return syscall6(
1415 .process_vm_readv,
1416 @bitCast(usize, @as(isize, pid)),
1417 @ptrToInt(local),
1418 local_count,
1419 @ptrToInt(remote),
1420 remote_count,
1421 flags,
1422 );
1423}
1424
1425pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
1426 return syscall6(
1427 .process_vm_writev,
1428 @bitCast(usize, @as(isize, pid)),
1429 @ptrToInt(local),
1430 local_count,
1431 @ptrToInt(remote),
1432 remote_count,
1433 flags,
1434 );
1435}
1436
1389test {1437test {
1390 if (std.Target.current.os.tag == .linux) {1438 if (std.Target.current.os.tag == .linux) {
1391 _ = @import("linux/test.zig");1439 _ = @import("linux/test.zig");
lib/std/os/linux/bpf/btf.zig+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6const magic = 0xeb9f;6const magic = 0xeb9f;
7const version = 1;7const version = 1;
88
9pub const ext = @import("ext.zig");9pub const ext = @import("btf_ext.zig");
1010
11/// All offsets are in bytes relative to the end of this header11/// All offsets are in bytes relative to the end of this header
12pub const Header = packed struct {12pub const Header = packed struct {
lib/std/os/windows/user32.zig+1-1
...@@ -663,7 +663,7 @@ pub fn messageBoxA(hWnd: ?HWND, lpText: [*:0]const u8, lpCaption: [*:0]const u8,...@@ -663,7 +663,7 @@ pub fn messageBoxA(hWnd: ?HWND, lpText: [*:0]const u8, lpCaption: [*:0]const u8,
663pub extern "user32" fn MessageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: ?[*:0]const u16, uType: UINT) callconv(WINAPI) i32;663pub extern "user32" fn MessageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: ?[*:0]const u16, uType: UINT) callconv(WINAPI) i32;
664pub var pfnMessageBoxW: @TypeOf(MessageBoxW) = undefined;664pub var pfnMessageBoxW: @TypeOf(MessageBoxW) = undefined;
665pub fn messageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: [*:0]const u16, uType: u32) !i32 {665pub fn messageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: [*:0]const u16, uType: u32) !i32 {
666 const function = selectSymbol(pfnMessageBoxW, MessageBoxW, .win2k);666 const function = selectSymbol(MessageBoxW, pfnMessageBoxW, .win2k);
667 const value = function(hWnd, lpText, lpCaption, uType);667 const value = function(hWnd, lpText, lpCaption, uType);
668 if (value != 0) return value;668 if (value != 0) return value;
669 switch (GetLastError()) {669 switch (GetLastError()) {
lib/std/special/c.zig+122-29
...@@ -88,7 +88,7 @@ test "strncpy" {...@@ -88,7 +88,7 @@ test "strncpy" {
88 var s1: [9:0]u8 = undefined;88 var s1: [9:0]u8 = undefined;
8989
90 s1[0] = 0;90 s1[0] = 0;
91 _ = strncpy(&s1, "foobarbaz", 9);91 _ = strncpy(&s1, "foobarbaz", @sizeOf(@TypeOf(s1)));
92 std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.spanZ(&s1));92 std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.spanZ(&s1));
93}93}
9494
...@@ -242,7 +242,7 @@ export fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) isiz...@@ -242,7 +242,7 @@ export fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) isiz
242 return 0;242 return 0;
243}243}
244244
245test "test_memcmp" {245test "memcmp" {
246 const base_arr = &[_]u8{ 1, 1, 1 };246 const base_arr = &[_]u8{ 1, 1, 1 };
247 const arr1 = &[_]u8{ 1, 1, 1 };247 const arr1 = &[_]u8{ 1, 1, 1 };
248 const arr2 = &[_]u8{ 1, 0, 1 };248 const arr2 = &[_]u8{ 1, 0, 1 };
...@@ -266,7 +266,7 @@ export fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) c...@@ -266,7 +266,7 @@ export fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) c
266 return 0;266 return 0;
267}267}
268268
269test "test_bcmp" {269test "bcmp" {
270 const base_arr = &[_]u8{ 1, 1, 1 };270 const base_arr = &[_]u8{ 1, 1, 1 };
271 const arr1 = &[_]u8{ 1, 1, 1 };271 const arr1 = &[_]u8{ 1, 1, 1 };
272 const arr2 = &[_]u8{ 1, 0, 1 };272 const arr2 = &[_]u8{ 1, 0, 1 };
...@@ -862,6 +862,85 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {...@@ -862,6 +862,85 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
862 return @bitCast(T, ux);862 return @bitCast(T, ux);
863}863}
864864
865test "fmod, fmodf" {
866 inline for ([_]type{ f32, f64 }) |T| {
867 const nan_val = math.nan(T);
868 const inf_val = math.inf(T);
869
870 std.testing.expect(isNan(generic_fmod(T, nan_val, 1.0)));
871 std.testing.expect(isNan(generic_fmod(T, 1.0, nan_val)));
872 std.testing.expect(isNan(generic_fmod(T, inf_val, 1.0)));
873 std.testing.expect(isNan(generic_fmod(T, 0.0, 0.0)));
874 std.testing.expect(isNan(generic_fmod(T, 1.0, 0.0)));
875
876 std.testing.expectEqual(@as(T, 0.0), generic_fmod(T, 0.0, 2.0));
877 std.testing.expectEqual(@as(T, -0.0), generic_fmod(T, -0.0, 2.0));
878
879 std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, 10.0));
880 std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, -10.0));
881 std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, 10.0));
882 std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, -10.0));
883 }
884}
885
886fn generic_fmin(comptime T: type, x: T, y: T) T {
887 if (isNan(x))
888 return y;
889 if (isNan(y))
890 return x;
891 return if (x < y) x else y;
892}
893
894export fn fminf(x: f32, y: f32) callconv(.C) f32 {
895 return generic_fmin(f32, x, y);
896}
897
898export fn fmin(x: f64, y: f64) callconv(.C) f64 {
899 return generic_fmin(f64, x, y);
900}
901
902test "fmin, fminf" {
903 inline for ([_]type{ f32, f64 }) |T| {
904 const nan_val = math.nan(T);
905
906 std.testing.expect(isNan(generic_fmin(T, nan_val, nan_val)));
907 std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, nan_val, 1.0));
908 std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, nan_val));
909
910 std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, 10.0));
911 std.testing.expectEqual(@as(T, -1.0), generic_fmin(T, 1.0, -1.0));
912 }
913}
914
915fn generic_fmax(comptime T: type, x: T, y: T) T {
916 if (isNan(x))
917 return y;
918 if (isNan(y))
919 return x;
920 return if (x < y) y else x;
921}
922
923export fn fmaxf(x: f32, y: f32) callconv(.C) f32 {
924 return generic_fmax(f32, x, y);
925}
926
927export fn fmax(x: f64, y: f64) callconv(.C) f64 {
928 return generic_fmax(f64, x, y);
929}
930
931test "fmax, fmaxf" {
932 inline for ([_]type{ f32, f64 }) |T| {
933 const nan_val = math.nan(T);
934
935 std.testing.expect(isNan(generic_fmax(T, nan_val, nan_val)));
936 std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, nan_val, 1.0));
937 std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, nan_val));
938
939 std.testing.expectEqual(@as(T, 10.0), generic_fmax(T, 1.0, 10.0));
940 std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, -1.0));
941 }
942}
943
865// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound944// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
866// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are945// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are
867// potentially some edge cases remaining that are not handled in the same way.946// potentially some edge cases remaining that are not handled in the same way.
...@@ -996,25 +1075,32 @@ export fn sqrt(x: f64) f64 {...@@ -996,25 +1075,32 @@ export fn sqrt(x: f64) f64 {
996}1075}
9971076
998test "sqrt" {1077test "sqrt" {
999 const epsilon = 0.000001;1078 const V = [_]f64{
10001079 0.0,
1001 std.testing.expect(sqrt(0.0) == 0.0);1080 4.089288054930154,
1002 std.testing.expect(std.math.approxEqAbs(f64, sqrt(2.0), 1.414214, epsilon));1081 7.538757127071935,
1003 std.testing.expect(std.math.approxEqAbs(f64, sqrt(3.6), 1.897367, epsilon));1082 8.97780793672623,
1004 std.testing.expect(sqrt(4.0) == 2.0);1083 5.304443821913729,
1005 std.testing.expect(std.math.approxEqAbs(f64, sqrt(7.539840), 2.745877, epsilon));1084 5.682408965311888,
1006 std.testing.expect(std.math.approxEqAbs(f64, sqrt(19.230934), 4.385309, epsilon));1085 0.5846878579110049,
1007 std.testing.expect(sqrt(64.0) == 8.0);1086 3.650338664297043,
1008 std.testing.expect(std.math.approxEqAbs(f64, sqrt(64.1), 8.006248, epsilon));1087 0.3178091951800732,
1009 std.testing.expect(std.math.approxEqAbs(f64, sqrt(8942.230469), 94.563367, epsilon));1088 7.1505232436382835,
1089 3.6589165881946464,
1090 };
1091
1092 // Note that @sqrt will either generate the sqrt opcode (if supported by the
1093 // target ISA) or a call to `sqrtf` otherwise.
1094 for (V) |val|
1095 std.testing.expectEqual(@sqrt(val), sqrt(val));
1010}1096}
10111097
1012test "sqrt special" {1098test "sqrt special" {
1013 std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64))));1099 std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64))));
1014 std.testing.expect(sqrt(0.0) == 0.0);1100 std.testing.expect(sqrt(0.0) == 0.0);
1015 std.testing.expect(sqrt(-0.0) == -0.0);1101 std.testing.expect(sqrt(-0.0) == -0.0);
1016 std.testing.expect(std.math.isNan(sqrt(-1.0)));1102 std.testing.expect(isNan(sqrt(-1.0)));
1017 std.testing.expect(std.math.isNan(sqrt(std.math.nan(f64))));1103 std.testing.expect(isNan(sqrt(std.math.nan(f64))));
1018}1104}
10191105
1020export fn sqrtf(x: f32) f32 {1106export fn sqrtf(x: f32) f32 {
...@@ -1094,23 +1180,30 @@ export fn sqrtf(x: f32) f32 {...@@ -1094,23 +1180,30 @@ export fn sqrtf(x: f32) f32 {
1094}1180}
10951181
1096test "sqrtf" {1182test "sqrtf" {
1097 const epsilon = 0.000001;1183 const V = [_]f32{
10981184 0.0,
1099 std.testing.expect(sqrtf(0.0) == 0.0);1185 4.089288054930154,
1100 std.testing.expect(std.math.approxEqAbs(f32, sqrtf(2.0), 1.414214, epsilon));1186 7.538757127071935,
1101 std.testing.expect(std.math.approxEqAbs(f32, sqrtf(3.6), 1.897367, epsilon));1187 8.97780793672623,
1102 std.testing.expect(sqrtf(4.0) == 2.0);1188 5.304443821913729,
1103 std.testing.expect(std.math.approxEqAbs(f32, sqrtf(7.539840), 2.745877, epsilon));1189 5.682408965311888,
1104 std.testing.expect(std.math.approxEqAbs(f32, sqrtf(19.230934), 4.385309, epsilon));1190 0.5846878579110049,
1105 std.testing.expect(sqrtf(64.0) == 8.0);1191 3.650338664297043,
1106 std.testing.expect(std.math.approxEqAbs(f32, sqrtf(64.1), 8.006248, epsilon));1192 0.3178091951800732,
1107 std.testing.expect(std.math.approxEqAbs(f32, sqrtf(8942.230469), 94.563370, epsilon));1193 7.1505232436382835,
1194 3.6589165881946464,
1195 };
1196
1197 // Note that @sqrt will either generate the sqrt opcode (if supported by the
1198 // target ISA) or a call to `sqrtf` otherwise.
1199 for (V) |val|
1200 std.testing.expectEqual(@sqrt(val), sqrtf(val));
1108}1201}
11091202
1110test "sqrtf special" {1203test "sqrtf special" {
1111 std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32))));1204 std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32))));
1112 std.testing.expect(sqrtf(0.0) == 0.0);1205 std.testing.expect(sqrtf(0.0) == 0.0);
1113 std.testing.expect(sqrtf(-0.0) == -0.0);1206 std.testing.expect(sqrtf(-0.0) == -0.0);
1114 std.testing.expect(std.math.isNan(sqrtf(-1.0)));1207 std.testing.expect(isNan(sqrtf(-1.0)));
1115 std.testing.expect(std.math.isNan(sqrtf(std.math.nan(f32))));1208 std.testing.expect(isNan(sqrtf(std.math.nan(f32))));
1116}1209}
lib/std/special/compiler_rt.zig+3-1
...@@ -116,9 +116,11 @@ comptime {...@@ -116,9 +116,11 @@ comptime {
116 @export(@import("compiler_rt/extendXfYf2.zig").__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });116 @export(@import("compiler_rt/extendXfYf2.zig").__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
117 @export(@import("compiler_rt/extendXfYf2.zig").__extendsftf2, .{ .name = "__extendsftf2", .linkage = linkage });117 @export(@import("compiler_rt/extendXfYf2.zig").__extendsftf2, .{ .name = "__extendsftf2", .linkage = linkage });
118 @export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = linkage });118 @export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = linkage });
119 @export(@import("compiler_rt/extendXfYf2.zig").__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage });
119120
120 @export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });121 @export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
121 @export(@import("compiler_rt/truncXfYf2.zig").__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });122 @export(@import("compiler_rt/truncXfYf2.zig").__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
123 @export(@import("compiler_rt/truncXfYf2.zig").__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
122 @export(@import("compiler_rt/truncXfYf2.zig").__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });124 @export(@import("compiler_rt/truncXfYf2.zig").__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
123 @export(@import("compiler_rt/truncXfYf2.zig").__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });125 @export(@import("compiler_rt/truncXfYf2.zig").__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
124126
...@@ -299,7 +301,7 @@ comptime {...@@ -299,7 +301,7 @@ comptime {
299 @export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });301 @export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });
300 }302 }
301303
302 if (arch == .powerpc or arch.isPPC64()) {304 if ((arch == .powerpc or arch.isPPC64()) and !is_test) {
303 @export(@import("compiler_rt/addXf3.zig").__addtf3, .{ .name = "__addkf3", .linkage = linkage });305 @export(@import("compiler_rt/addXf3.zig").__addtf3, .{ .name = "__addkf3", .linkage = linkage });
304 @export(@import("compiler_rt/addXf3.zig").__subtf3, .{ .name = "__subkf3", .linkage = linkage });306 @export(@import("compiler_rt/addXf3.zig").__subtf3, .{ .name = "__subkf3", .linkage = linkage });
305 @export(@import("compiler_rt/mulXf3.zig").__multf3, .{ .name = "__mulkf3", .linkage = linkage });307 @export(@import("compiler_rt/mulXf3.zig").__multf3, .{ .name = "__mulkf3", .linkage = linkage });
lib/std/special/compiler_rt/extendXfYf2.zig+4
...@@ -23,6 +23,10 @@ pub fn __extendhfsf2(a: u16) callconv(.C) f32 {...@@ -23,6 +23,10 @@ pub fn __extendhfsf2(a: u16) callconv(.C) f32 {
23 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, a });23 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, a });
24}24}
2525
26pub fn __extendhftf2(a: u16) callconv(.C) f128 {
27 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f16, a });
28}
29
26pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 {30pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 {
27 @setRuntimeSafety(false);31 @setRuntimeSafety(false);
28 return @call(.{ .modifier = .always_inline }, __extendhfsf2, .{arg});32 return @call(.{ .modifier = .always_inline }, __extendhfsf2, .{arg});
lib/std/special/compiler_rt/extendXfYf2_test.zig+48-1
...@@ -4,9 +4,10 @@...@@ -4,9 +4,10 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
8const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;7const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
8const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2;
9const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;9const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
10const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
1011
11fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {12fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {
12 const x = __extenddftf2(a);13 const x = __extenddftf2(a);
...@@ -161,3 +162,49 @@ fn makeNaN32(rand: u32) f32 {...@@ -161,3 +162,49 @@ fn makeNaN32(rand: u32) f32 {
161fn makeInf32() f32 {162fn makeInf32() f32 {
162 return @bitCast(f32, @as(u32, 0x7f800000));163 return @bitCast(f32, @as(u32, 0x7f800000));
163}164}
165
166fn test__extendhftf2(a: u16, expectedHi: u64, expectedLo: u64) void {
167 const x = __extendhftf2(a);
168
169 const rep = @bitCast(u128, x);
170 const hi = @intCast(u64, rep >> 64);
171 const lo = @truncate(u64, rep);
172
173 if (hi == expectedHi and lo == expectedLo)
174 return;
175
176 // test other possible NaN representation(signal NaN)
177 if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) {
178 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
179 ((hi & 0xffffffffffff) > 0 or lo > 0))
180 {
181 return;
182 }
183 }
184
185 @panic("__extendhftf2 test failure");
186}
187
188test "extendhftf2" {
189 // qNaN
190 test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0);
191 // NaN
192 test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0);
193 // inf
194 test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0);
195 test__extendhftf2(0xfc00, 0xffff000000000000, 0x0);
196 // zero
197 test__extendhftf2(0x0000, 0x0000000000000000, 0x0);
198 test__extendhftf2(0x8000, 0x8000000000000000, 0x0);
199 // denormal
200 test__extendhftf2(0x0010, 0x3feb000000000000, 0x0);
201 test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0);
202 test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0);
203
204 // pi
205 test__extendhftf2(0x4248, 0x4000920000000000, 0x0);
206 test__extendhftf2(0xc248, 0xc000920000000000, 0x0);
207
208 test__extendhftf2(0x508c, 0x4004230000000000, 0x0);
209 test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0);
210}
lib/std/special/compiler_rt/truncXfYf2.zig+5-1
...@@ -13,6 +13,10 @@ pub fn __truncdfhf2(a: f64) callconv(.C) u16 {...@@ -13,6 +13,10 @@ pub fn __truncdfhf2(a: f64) callconv(.C) u16 {
13 return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a }));13 return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a }));
14}14}
1515
16pub fn __trunctfhf2(a: f128) callconv(.C) u16 {
17 return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a }));
18}
19
16pub fn __trunctfsf2(a: f128) callconv(.C) f32 {20pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
17 return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f128, a });21 return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f128, a });
18}22}
...@@ -122,7 +126,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {...@@ -122,7 +126,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
122 if (shift > srcSigBits) {126 if (shift > srcSigBits) {
123 absResult = 0;127 absResult = 0;
124 } else {128 } else {
125 const sticky: src_rep_t = significand << @intCast(SrcShift, srcBits - shift);129 const sticky: src_rep_t = @boolToInt(significand << @intCast(SrcShift, srcBits - shift) != 0);
126 const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky;130 const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky;
127 absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits));131 absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits));
128 const roundBits: src_rep_t = denormalizedSignificand & roundMask;132 const roundBits: src_rep_t = denormalizedSignificand & roundMask;
lib/std/special/compiler_rt/truncXfYf2_test.zig+56
...@@ -242,3 +242,59 @@ test "truncdfsf2" {...@@ -242,3 +242,59 @@ test "truncdfsf2" {
242 // huge number becomes inf242 // huge number becomes inf
243 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);243 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
244}244}
245
246const __trunctfhf2 = @import("truncXfYf2.zig").__trunctfhf2;
247
248fn test__trunctfhf2(a: f128, expected: u16) void {
249 const x = __trunctfhf2(a);
250
251 const rep = @bitCast(u16, x);
252 if (rep == expected) {
253 return;
254 }
255
256 @import("std").debug.warn("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
257
258 @panic("__trunctfhf2 test failure");
259}
260
261test "trunctfhf2" {
262 // qNaN
263 test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
264 // NaN
265 test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
266 // inf
267 test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
268 test__trunctfhf2(-@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0xfc00);
269 // zero
270 test__trunctfhf2(0.0, 0x0);
271 test__trunctfhf2(-0.0, 0x8000);
272
273 test__trunctfhf2(3.1415926535, 0x4248);
274 test__trunctfhf2(-3.1415926535, 0xc248);
275 test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);
276 test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);
277 test__trunctfhf2(0x1.0p+0, 0x3c00);
278 test__trunctfhf2(0x1.0p-14, 0x0400);
279 // denormal
280 test__trunctfhf2(0x1.0p-20, 0x0010);
281 test__trunctfhf2(0x1.0p-24, 0x0001);
282 test__trunctfhf2(-0x1.0p-24, 0x8001);
283 test__trunctfhf2(0x1.5p-25, 0x0001);
284 // and back to zero
285 test__trunctfhf2(0x1.0p-25, 0x0000);
286 test__trunctfhf2(-0x1.0p-25, 0x8000);
287 // max (precise)
288 test__trunctfhf2(65504.0, 0x7bff);
289 // max (rounded)
290 test__trunctfhf2(65519.0, 0x7bff);
291 // max (to +inf)
292 test__trunctfhf2(65520.0, 0x7c00);
293 test__trunctfhf2(65536.0, 0x7c00);
294 test__trunctfhf2(-65520.0, 0xfc00);
295
296 test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
297 test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
298 test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
299 test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
300}
lib/std/target.zig+9-2
...@@ -800,6 +800,13 @@ pub const Target = struct {...@@ -800,6 +800,13 @@ pub const Target = struct {
800 };800 };
801 }801 }
802802
803 pub fn isPPC(arch: Arch) bool {
804 return switch (arch) {
805 .powerpc, .powerpcle => true,
806 else => false,
807 };
808 }
809
803 pub fn isPPC64(arch: Arch) bool {810 pub fn isPPC64(arch: Arch) bool {
804 return switch (arch) {811 return switch (arch) {
805 .powerpc64, .powerpc64le => true,812 .powerpc64, .powerpc64le => true,
...@@ -1184,8 +1191,8 @@ pub const Target = struct {...@@ -1184,8 +1191,8 @@ pub const Target = struct {
1184 .mips, .mipsel => &mips.cpu.mips32,1191 .mips, .mipsel => &mips.cpu.mips32,
1185 .mips64, .mips64el => &mips.cpu.mips64,1192 .mips64, .mips64el => &mips.cpu.mips64,
1186 .msp430 => &msp430.cpu.generic,1193 .msp430 => &msp430.cpu.generic,
1187 .powerpc => &powerpc.cpu.ppc32,1194 .powerpc => &powerpc.cpu.ppc,
1188 .powerpcle => &powerpc.cpu.ppc32,1195 .powerpcle => &powerpc.cpu.ppc,
1189 .powerpc64 => &powerpc.cpu.ppc64,1196 .powerpc64 => &powerpc.cpu.ppc64,
1190 .powerpc64le => &powerpc.cpu.ppc64le,1197 .powerpc64le => &powerpc.cpu.ppc64le,
1191 .amdgcn => &amdgpu.cpu.generic,1198 .amdgcn => &amdgpu.cpu.generic,
lib/std/target/powerpc.zig-7
...@@ -751,13 +751,6 @@ pub const cpu = struct {...@@ -751,13 +751,6 @@ pub const cpu = struct {
751 .hard_float,751 .hard_float,
752 }),752 }),
753 };753 };
754 pub const ppc32 = CpuModel{
755 .name = "ppc32",
756 .llvm_name = "ppc32",
757 .features = featureSet(&[_]Feature{
758 .hard_float,
759 }),
760 };
761 pub const ppc64 = CpuModel{754 pub const ppc64 = CpuModel{
762 .name = "ppc64",755 .name = "ppc64",
763 .llvm_name = "ppc64",756 .llvm_name = "ppc64",
lib/std/zig/parse.zig+2-1
...@@ -852,7 +852,7 @@ const Parser = struct {...@@ -852,7 +852,7 @@ const Parser = struct {
852 /// <- KEYWORD_comptime? VarDecl852 /// <- KEYWORD_comptime? VarDecl
853 /// / KEYWORD_comptime BlockExprStatement853 /// / KEYWORD_comptime BlockExprStatement
854 /// / KEYWORD_nosuspend BlockExprStatement854 /// / KEYWORD_nosuspend BlockExprStatement
855 /// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)855 /// / KEYWORD_suspend BlockExprStatement
856 /// / KEYWORD_defer BlockExprStatement856 /// / KEYWORD_defer BlockExprStatement
857 /// / KEYWORD_errdefer Payload? BlockExprStatement857 /// / KEYWORD_errdefer Payload? BlockExprStatement
858 /// / IfStatement858 /// / IfStatement
...@@ -892,6 +892,7 @@ const Parser = struct {...@@ -892,6 +892,7 @@ const Parser = struct {
892 },892 },
893 .keyword_suspend => {893 .keyword_suspend => {
894 const token = p.nextToken();894 const token = p.nextToken();
895 // TODO remove this special case when 0.9.0 is released.
895 const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)896 const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)
896 0897 0
897 else898 else
lib/std/zig/parser_test.zig+54-3
...@@ -40,6 +40,21 @@ test "zig fmt: rewrite inline functions as callconv(.Inline)" {...@@ -40,6 +40,21 @@ test "zig fmt: rewrite inline functions as callconv(.Inline)" {
40 );40 );
41}41}
4242
43// TODO Remove this after zig 0.9.0 is released.
44test "zig fmt: rewrite suspend without block expression" {
45 try testTransform(
46 \\fn foo() void {
47 \\ suspend;
48 \\}
49 \\
50 ,
51 \\fn foo() void {
52 \\ suspend {}
53 \\}
54 \\
55 );
56}
57
43test "zig fmt: simple top level comptime block" {58test "zig fmt: simple top level comptime block" {
44 try testCanonical(59 try testCanonical(
45 \\// line comment60 \\// line comment
...@@ -1315,6 +1330,27 @@ test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {...@@ -1315,6 +1330,27 @@ test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
1315 );1330 );
1316}1331}
13171332
1333test "zig fmt: 'zig fmt: on' indentation is unchanged" {
1334 try testCanonical(
1335 \\fn initOptionsAndLayouts(output: *Output, context: *Context) !void {
1336 \\ // zig fmt: off
1337 \\ try output.main_amount.init(output, "main_amount"); errdefer optput.main_amount.deinit();
1338 \\ try output.main_factor.init(output, "main_factor"); errdefer optput.main_factor.deinit();
1339 \\ try output.view_padding.init(output, "view_padding"); errdefer optput.view_padding.deinit();
1340 \\ try output.outer_padding.init(output, "outer_padding"); errdefer optput.outer_padding.deinit();
1341 \\ // zig fmt: on
1342 \\
1343 \\ // zig fmt: off
1344 \\ try output.top.init(output, .top); errdefer optput.top.deinit();
1345 \\ try output.right.init(output, .right); errdefer optput.right.deinit();
1346 \\ try output.bottom.init(output, .bottom); errdefer optput.bottom.deinit();
1347 \\ try output.left.init(output, .left); errdefer optput.left.deinit();
1348 \\ // zig fmt: on
1349 \\}
1350 \\
1351 );
1352}
1353
1318test "zig fmt: pointer of unknown length" {1354test "zig fmt: pointer of unknown length" {
1319 try testCanonical(1355 try testCanonical(
1320 \\fn foo(ptr: [*]u8) void {}1356 \\fn foo(ptr: [*]u8) void {}
...@@ -3644,9 +3680,9 @@ test "zig fmt: async functions" {...@@ -3644,9 +3680,9 @@ test "zig fmt: async functions" {
3644 \\fn simpleAsyncFn() void {3680 \\fn simpleAsyncFn() void {
3645 \\ const a = async a.b();3681 \\ const a = async a.b();
3646 \\ x += 1;3682 \\ x += 1;
3647 \\ suspend;3683 \\ suspend {}
3648 \\ x += 1;3684 \\ x += 1;
3649 \\ suspend;3685 \\ suspend {}
3650 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;3686 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
3651 \\ await p;3687 \\ await p;
3652 \\}3688 \\}
...@@ -5001,6 +5037,21 @@ test "recovery: invalid comptime" {...@@ -5001,6 +5037,21 @@ test "recovery: invalid comptime" {
5001 });5037 });
5002}5038}
50035039
5040test "recovery: missing block after suspend" {
5041 // TODO Enable this after zig 0.9.0 is released.
5042 if (true) return error.SkipZigTest;
5043
5044 try testError(
5045 \\fn foo() void {
5046 \\ suspend;
5047 \\ nosuspend;
5048 \\}
5049 , &[_]Error{
5050 .expected_block_or_expr,
5051 .expected_block_or_expr,
5052 });
5053}
5054
5004test "recovery: missing block after for/while loops" {5055test "recovery: missing block after for/while loops" {
5005 try testError(5056 try testError(
5006 \\test "" { while (foo) }5057 \\test "" { while (foo) }
...@@ -5144,7 +5195,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {...@@ -5144,7 +5195,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
5144 var tree = try std.zig.parse(std.testing.allocator, source);5195 var tree = try std.zig.parse(std.testing.allocator, source);
5145 defer tree.deinit(std.testing.allocator);5196 defer tree.deinit(std.testing.allocator);
51465197
5147 std.testing.expect(tree.errors.len == expected_errors.len);5198 std.testing.expectEqual(expected_errors.len, tree.errors.len);
5148 for (expected_errors) |expected, i| {5199 for (expected_errors) |expected, i| {
5149 std.testing.expectEqual(expected, tree.errors[i].tag);5200 std.testing.expectEqual(expected, tree.errors[i].tag);
5150 }5201 }
lib/std/zig/render.zig+8-3
...@@ -269,7 +269,12 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I...@@ -269,7 +269,12 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I
269 try renderToken(ais, tree, suspend_token, .space);269 try renderToken(ais, tree, suspend_token, .space);
270 return renderExpression(gpa, ais, tree, body, space);270 return renderExpression(gpa, ais, tree, body, space);
271 } else {271 } else {
272 return renderToken(ais, tree, suspend_token, space);272 // TODO remove this special case when 0.9.0 is released.
273 assert(space == .semicolon);
274 try renderToken(ais, tree, suspend_token, .space);
275 try ais.writer().writeAll("{}");
276 try ais.insertNewline();
277 return;
273 }278 }
274 },279 },
275280
...@@ -2310,9 +2315,9 @@ fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!boo...@@ -2310,9 +2315,9 @@ fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!boo
2310 // to the underlying writer, fixing up invaild whitespace.2315 // to the underlying writer, fixing up invaild whitespace.
2311 const disabled_source = tree.source[ais.disabled_offset.?..comment_start];2316 const disabled_source = tree.source[ais.disabled_offset.?..comment_start];
2312 try writeFixingWhitespace(ais.underlying_writer, disabled_source);2317 try writeFixingWhitespace(ais.underlying_writer, disabled_source);
2313 ais.disabled_offset = null;
2314 // Write with the canonical single space.2318 // Write with the canonical single space.
2315 try ais.writer().writeAll("// zig fmt: on\n");2319 try ais.underlying_writer.writeAll("// zig fmt: on\n");
2320 ais.disabled_offset = null;
2316 } else if (ais.disabled_offset == null and mem.eql(u8, comment_content, "zig fmt: off")) {2321 } else if (ais.disabled_offset == null and mem.eql(u8, comment_content, "zig fmt: off")) {
2317 // Write with the canonical single space.2322 // Write with the canonical single space.
2318 try ais.writer().writeAll("// zig fmt: off\n");2323 try ais.writer().writeAll("// zig fmt: off\n");
src/Compilation.zig+19-15
...@@ -2856,25 +2856,29 @@ pub fn addCCArgs(...@@ -2856,25 +2856,29 @@ pub fn addCCArgs(
2856 try argv.append("-fPIC");2856 try argv.append("-fPIC");
2857 }2857 }
2858 },2858 },
2859 .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig => {},2859 .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
2860 .assembly => {
2861 // Argh, why doesn't the assembler accept the list of CPU features?!
2862 // I don't see a way to do this other than hard coding everything.
2863 switch (target.cpu.arch) {
2864 .riscv32, .riscv64 => {
2865 if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
2866 try argv.append("-mrelax");
2867 } else {
2868 try argv.append("-mno-relax");
2869 }
2870 },
2871 else => {
2872 // TODO
2873 },
2874 }
2875 if (target.cpu.model.llvm_name) |ln|
2876 try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{ln}));
2877 },
2860 }2878 }
2861 if (out_dep_path) |p| {2879 if (out_dep_path) |p| {
2862 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });2880 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
2863 }2881 }
2864 // Argh, why doesn't the assembler accept the list of CPU features?!
2865 // I don't see a way to do this other than hard coding everything.
2866 switch (target.cpu.arch) {
2867 .riscv32, .riscv64 => {
2868 if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
2869 try argv.append("-mrelax");
2870 } else {
2871 try argv.append("-mno-relax");
2872 }
2873 },
2874 else => {
2875 // TODO
2876 },
2877 }
28782882
2879 if (target.os.tag == .freestanding) {2883 if (target.os.tag == .freestanding) {
2880 try argv.append("-ffreestanding");2884 try argv.append("-ffreestanding");
src/codegen.zig-1
...@@ -1247,7 +1247,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1247,7 +1247,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1247 },1247 },
1248 .stack_offset => |off| {1248 .stack_offset => |off| {
1249 log.debug("reusing stack offset {} => {*}", .{ off, inst });1249 log.debug("reusing stack offset {} => {*}", .{ off, inst });
1250 return true;
1251 },1250 },
1252 else => return false,1251 else => return false,
1253 }1252 }
src/link/MachO.zig+1-2
...@@ -645,8 +645,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -645,8 +645,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
645 break :blk true;645 break :blk true;
646 }646 }
647647
648 if (self.base.options.link_libcpp or648 if (self.base.options.output_mode == .Lib or
649 self.base.options.output_mode == .Lib or
650 self.base.options.linker_script != null)649 self.base.options.linker_script != null)
651 {650 {
652 // Fallback to LLD in this handful of cases on x86_64 only.651 // Fallback to LLD in this handful of cases on x86_64 only.
src/link/MachO/Archive.zig+2-3
...@@ -208,14 +208,13 @@ pub fn parseObject(self: Archive, offset: u32) !Object {...@@ -208,14 +208,13 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
208208
209 const object_name = try parseName(self.allocator, object_header, reader);209 const object_name = try parseName(self.allocator, object_header, reader);
210 defer self.allocator.free(object_name);210 defer self.allocator.free(object_name);
211 const object_basename = std.fs.path.basename(object_name);
212211
213 log.debug("extracting object '{s}' from archive '{s}'", .{ object_basename, self.name.? });212 log.debug("extracting object '{s}' from archive '{s}'", .{ object_name, self.name.? });
214213
215 const name = name: {214 const name = name: {
216 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;215 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
217 const path = try std.os.realpath(self.name.?, &buffer);216 const path = try std.os.realpath(self.name.?, &buffer);
218 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_basename });217 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });
219 };218 };
220219
221 var object = Object.init(self.allocator);220 var object = Object.init(self.allocator);
src/link/MachO/Object.zig+43-4
...@@ -32,7 +32,9 @@ symtab_cmd_index: ?u16 = null,...@@ -32,7 +32,9 @@ symtab_cmd_index: ?u16 = null,
32dysymtab_cmd_index: ?u16 = null,32dysymtab_cmd_index: ?u16 = null,
33build_version_cmd_index: ?u16 = null,33build_version_cmd_index: ?u16 = null,
34data_in_code_cmd_index: ?u16 = null,34data_in_code_cmd_index: ?u16 = null,
35
35text_section_index: ?u16 = null,36text_section_index: ?u16 = null,
37mod_init_func_section_index: ?u16 = null,
3638
37// __DWARF segment sections39// __DWARF segment sections
38dwarf_debug_info_index: ?u16 = null,40dwarf_debug_info_index: ?u16 = null,
...@@ -49,6 +51,7 @@ stabs: std.ArrayListUnmanaged(Stab) = .{},...@@ -49,6 +51,7 @@ stabs: std.ArrayListUnmanaged(Stab) = .{},
49tu_path: ?[]const u8 = null,51tu_path: ?[]const u8 = null,
50tu_mtime: ?u64 = null,52tu_mtime: ?u64 = null,
5153
54initializers: std.ArrayListUnmanaged(CppStatic) = .{},
52data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},55data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
5356
54pub const Section = struct {57pub const Section = struct {
...@@ -68,6 +71,11 @@ pub const Section = struct {...@@ -68,6 +71,11 @@ pub const Section = struct {
68 }71 }
69};72};
7073
74const CppStatic = struct {
75 symbol: u32,
76 target_addr: u64,
77};
78
71const Stab = struct {79const Stab = struct {
72 tag: Tag,80 tag: Tag,
73 symbol: u32,81 symbol: u32,
...@@ -170,6 +178,7 @@ pub fn deinit(self: *Object) void {...@@ -170,6 +178,7 @@ pub fn deinit(self: *Object) void {
170 self.strtab.deinit(self.allocator);178 self.strtab.deinit(self.allocator);
171 self.stabs.deinit(self.allocator);179 self.stabs.deinit(self.allocator);
172 self.data_in_code_entries.deinit(self.allocator);180 self.data_in_code_entries.deinit(self.allocator);
181 self.initializers.deinit(self.allocator);
173182
174 if (self.name) |n| {183 if (self.name) |n| {
175 self.allocator.free(n);184 self.allocator.free(n);
...@@ -216,6 +225,7 @@ pub fn parse(self: *Object) !void {...@@ -216,6 +225,7 @@ pub fn parse(self: *Object) !void {
216 try self.parseSections();225 try self.parseSections();
217 if (self.symtab_cmd_index != null) try self.parseSymtab();226 if (self.symtab_cmd_index != null) try self.parseSymtab();
218 if (self.data_in_code_cmd_index != null) try self.readDataInCode();227 if (self.data_in_code_cmd_index != null) try self.readDataInCode();
228 try self.parseInitializers();
219 try self.parseDebugInfo();229 try self.parseDebugInfo();
220}230}
221231
...@@ -250,6 +260,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -250,6 +260,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
250 if (mem.eql(u8, sectname, "__text")) {260 if (mem.eql(u8, sectname, "__text")) {
251 self.text_section_index = index;261 self.text_section_index = index;
252 }262 }
263 } else if (mem.eql(u8, segname, "__DATA")) {
264 if (mem.eql(u8, sectname, "__mod_init_func")) {
265 self.mod_init_func_section_index = index;
266 }
253 }267 }
254268
255 sect.offset += offset;269 sect.offset += offset;
...@@ -298,28 +312,53 @@ pub fn parseSections(self: *Object) !void {...@@ -298,28 +312,53 @@ pub fn parseSections(self: *Object) !void {
298 var section = Section{312 var section = Section{
299 .inner = sect,313 .inner = sect,
300 .code = code,314 .code = code,
301 .relocs = undefined,315 .relocs = null,
302 };316 };
303317
304 // Parse relocations318 // Parse relocations
305 section.relocs = if (sect.nreloc > 0) relocs: {319 if (sect.nreloc > 0) {
306 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);320 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
307 defer self.allocator.free(raw_relocs);321 defer self.allocator.free(raw_relocs);
308322
309 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);323 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
310324
311 break :relocs try reloc.parse(325 section.relocs = try reloc.parse(
312 self.allocator,326 self.allocator,
313 self.arch.?,327 self.arch.?,
314 section.code,328 section.code,
315 mem.bytesAsSlice(macho.relocation_info, raw_relocs),329 mem.bytesAsSlice(macho.relocation_info, raw_relocs),
316 );330 );
317 } else null;331 }
318332
319 self.sections.appendAssumeCapacity(section);333 self.sections.appendAssumeCapacity(section);
320 }334 }
321}335}
322336
337pub fn parseInitializers(self: *Object) !void {
338 const index = self.mod_init_func_section_index orelse return;
339 const section = self.sections.items[index];
340
341 log.debug("parsing initializers in {s}", .{self.name.?});
342
343 // Parse C++ initializers
344 const relocs = section.relocs orelse unreachable;
345 try self.initializers.ensureCapacity(self.allocator, relocs.len);
346 for (relocs) |rel| {
347 self.initializers.appendAssumeCapacity(.{
348 .symbol = rel.target.symbol,
349 .target_addr = undefined,
350 });
351 }
352
353 mem.reverse(CppStatic, self.initializers.items);
354
355 for (self.initializers.items) |initializer| {
356 const sym = self.symtab.items[initializer.symbol];
357 const sym_name = self.getString(sym.n_strx);
358 log.debug(" | {s}", .{sym_name});
359 }
360}
361
323pub fn parseSymtab(self: *Object) !void {362pub fn parseSymtab(self: *Object) !void {
324 const symtab_cmd = self.load_commands.items[self.symtab_cmd_index.?].Symtab;363 const symtab_cmd = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
325364
src/link/MachO/Symbol.zig+1-1
...@@ -52,7 +52,7 @@ pub fn isUndf(sym: macho.nlist_64) bool {...@@ -52,7 +52,7 @@ pub fn isUndf(sym: macho.nlist_64) bool {
52}52}
5353
54pub fn isWeakDef(sym: macho.nlist_64) bool {54pub fn isWeakDef(sym: macho.nlist_64) bool {
55 return sym.n_desc == macho.N_WEAK_DEF;55 return (sym.n_desc & macho.N_WEAK_DEF) != 0;
56}56}
5757
58/// Symbol is local if it is defined and not an extern.58/// Symbol is local if it is defined and not an extern.
src/link/MachO/Zld.zig+157-67
...@@ -72,6 +72,7 @@ tlv_bss_section_index: ?u16 = null,...@@ -72,6 +72,7 @@ tlv_bss_section_index: ?u16 = null,
72la_symbol_ptr_section_index: ?u16 = null,72la_symbol_ptr_section_index: ?u16 = null,
73data_section_index: ?u16 = null,73data_section_index: ?u16 = null,
74bss_section_index: ?u16 = null,74bss_section_index: ?u16 = null,
75common_section_index: ?u16 = null,
7576
76symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},77symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},
77strtab: std.ArrayListUnmanaged(u8) = .{},78strtab: std.ArrayListUnmanaged(u8) = .{},
...@@ -224,6 +225,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {...@@ -224,6 +225,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
224 self.allocateLinkeditSegment();225 self.allocateLinkeditSegment();
225 try self.allocateSymbols();226 try self.allocateSymbols();
226 try self.allocateStubsAndGotEntries();227 try self.allocateStubsAndGotEntries();
228 try self.allocateCppStatics();
227 try self.writeStubHelperCommon();229 try self.writeStubHelperCommon();
228 try self.resolveRelocsAndWriteSections();230 try self.resolveRelocsAndWriteSections();
229 try self.flush();231 try self.flush();
...@@ -465,23 +467,43 @@ fn updateMetadata(self: *Zld) !void {...@@ -465,23 +467,43 @@ fn updateMetadata(self: *Zld) !void {
465 },467 },
466 macho.S_ZEROFILL => {468 macho.S_ZEROFILL => {
467 if (!mem.eql(u8, segname, "__DATA")) continue;469 if (!mem.eql(u8, segname, "__DATA")) continue;
468 if (self.bss_section_index != null) continue;470 if (mem.eql(u8, sectname, "__common")) {
471 if (self.common_section_index != null) continue;
469472
470 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);473 self.common_section_index = @intCast(u16, data_seg.sections.items.len);
471 try data_seg.addSection(self.allocator, .{474 try data_seg.addSection(self.allocator, .{
472 .sectname = makeStaticString("__bss"),475 .sectname = makeStaticString("__common"),
473 .segname = makeStaticString("__DATA"),476 .segname = makeStaticString("__DATA"),
474 .addr = 0,477 .addr = 0,
475 .size = 0,478 .size = 0,
476 .offset = 0,479 .offset = 0,
477 .@"align" = 0,480 .@"align" = 0,
478 .reloff = 0,481 .reloff = 0,
479 .nreloc = 0,482 .nreloc = 0,
480 .flags = macho.S_ZEROFILL,483 .flags = macho.S_ZEROFILL,
481 .reserved1 = 0,484 .reserved1 = 0,
482 .reserved2 = 0,485 .reserved2 = 0,
483 .reserved3 = 0,486 .reserved3 = 0,
484 });487 });
488 } else {
489 if (self.bss_section_index != null) continue;
490
491 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
492 try data_seg.addSection(self.allocator, .{
493 .sectname = makeStaticString("__bss"),
494 .segname = makeStaticString("__DATA"),
495 .addr = 0,
496 .size = 0,
497 .offset = 0,
498 .@"align" = 0,
499 .reloff = 0,
500 .nreloc = 0,
501 .flags = macho.S_ZEROFILL,
502 .reserved1 = 0,
503 .reserved2 = 0,
504 .reserved3 = 0,
505 });
506 }
485 },507 },
486 macho.S_THREAD_LOCAL_VARIABLES => {508 macho.S_THREAD_LOCAL_VARIABLES => {
487 if (!mem.eql(u8, segname, "__DATA")) continue;509 if (!mem.eql(u8, segname, "__DATA")) continue;
...@@ -568,7 +590,9 @@ fn updateMetadata(self: *Zld) !void {...@@ -568,7 +590,9 @@ fn updateMetadata(self: *Zld) !void {
568590
569 const segname = parseName(&source_sect.segname);591 const segname = parseName(&source_sect.segname);
570 const sectname = parseName(&source_sect.sectname);592 const sectname = parseName(&source_sect.sectname);
593
571 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });594 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });
595
572 try self.unhandled_sections.putNoClobber(self.allocator, .{596 try self.unhandled_sections.putNoClobber(self.allocator, .{
573 .object_id = object_id,597 .object_id = object_id,
574 .source_sect_id = source_sect_id,598 .source_sect_id = source_sect_id,
...@@ -585,6 +609,7 @@ const MatchingSection = struct {...@@ -585,6 +609,7 @@ const MatchingSection = struct {
585fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {609fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
586 const segname = parseName(&section.segname);610 const segname = parseName(&section.segname);
587 const sectname = parseName(&section.sectname);611 const sectname = parseName(&section.sectname);
612
588 const res: ?MatchingSection = blk: {613 const res: ?MatchingSection = blk: {
589 switch (section.flags) {614 switch (section.flags) {
590 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {615 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
...@@ -612,6 +637,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -612,6 +637,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
612 };637 };
613 },638 },
614 macho.S_ZEROFILL => {639 macho.S_ZEROFILL => {
640 if (mem.eql(u8, sectname, "__common")) {
641 break :blk .{
642 .seg = self.data_segment_cmd_index.?,
643 .sect = self.common_section_index.?,
644 };
645 }
615 break :blk .{646 break :blk .{
616 .seg = self.data_segment_cmd_index.?,647 .seg = self.data_segment_cmd_index.?,
617 .sect = self.bss_section_index.?,648 .sect = self.bss_section_index.?,
...@@ -667,6 +698,7 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -667,6 +698,7 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
667 },698 },
668 }699 }
669 };700 };
701
670 return res;702 return res;
671}703}
672704
...@@ -737,11 +769,12 @@ fn sortSections(self: *Zld) !void {...@@ -737,11 +769,12 @@ fn sortSections(self: *Zld) !void {
737 // __DATA segment769 // __DATA segment
738 const indices = &[_]*?u16{770 const indices = &[_]*?u16{
739 &self.la_symbol_ptr_section_index,771 &self.la_symbol_ptr_section_index,
740 &self.tlv_section_index,
741 &self.data_section_index,772 &self.data_section_index,
773 &self.tlv_section_index,
742 &self.tlv_data_section_index,774 &self.tlv_data_section_index,
743 &self.tlv_bss_section_index,775 &self.tlv_bss_section_index,
744 &self.bss_section_index,776 &self.bss_section_index,
777 &self.common_section_index,
745 };778 };
746 for (indices) |maybe_index| {779 for (indices) |maybe_index| {
747 const new_index: u16 = if (maybe_index.*) |index| blk: {780 const new_index: u16 = if (maybe_index.*) |index| blk: {
...@@ -959,6 +992,21 @@ fn allocateStubsAndGotEntries(self: *Zld) !void {...@@ -959,6 +992,21 @@ fn allocateStubsAndGotEntries(self: *Zld) !void {
959 }992 }
960}993}
961994
995fn allocateCppStatics(self: *Zld) !void {
996 for (self.objects.items) |*object| {
997 for (object.initializers.items) |*initializer| {
998 const sym = object.symtab.items[initializer.symbol];
999 const sym_name = object.getString(sym.n_strx);
1000 initializer.target_addr = object.locals.get(sym_name).?.address;
1001
1002 log.debug("resolving C++ initializer '{s}' at 0x{x}", .{
1003 sym_name,
1004 initializer.target_addr,
1005 });
1006 }
1007 }
1008}
1009
962fn writeStubHelperCommon(self: *Zld) !void {1010fn writeStubHelperCommon(self: *Zld) !void {
963 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;1011 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
964 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];1012 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
...@@ -1236,11 +1284,12 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {...@@ -1236,11 +1284,12 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {
1236 continue;1284 continue;
1237 } else if (Symbol.isGlobal(sym)) {1285 } else if (Symbol.isGlobal(sym)) {
1238 const sym_name = object.getString(sym.n_strx);1286 const sym_name = object.getString(sym.n_strx);
1287 const is_weak = Symbol.isWeakDef(sym) or Symbol.isPext(sym);
1239 const global = self.symtab.getEntry(sym_name) orelse {1288 const global = self.symtab.getEntry(sym_name) orelse {
1240 // Put new global symbol into the symbol table.1289 // Put new global symbol into the symbol table.
1241 const name = try self.allocator.dupe(u8, sym_name);1290 const name = try self.allocator.dupe(u8, sym_name);
1242 try self.symtab.putNoClobber(self.allocator, name, .{1291 try self.symtab.putNoClobber(self.allocator, name, .{
1243 .tag = if (Symbol.isWeakDef(sym)) .weak else .strong,1292 .tag = if (is_weak) .weak else .strong,
1244 .name = name,1293 .name = name,
1245 .address = 0,1294 .address = 0,
1246 .section = 0,1295 .section = 0,
...@@ -1251,15 +1300,20 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {...@@ -1251,15 +1300,20 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {
1251 };1300 };
12521301
1253 switch (global.value.tag) {1302 switch (global.value.tag) {
1254 .weak => continue, // If symbol is weak, nothing to do.1303 .weak => {
1304 if (is_weak) continue; // Nothing to do for weak symbol.
1305 },
1255 .strong => {1306 .strong => {
1256 log.err("symbol '{s}' defined multiple times", .{sym_name});1307 if (!is_weak) {
1257 return error.MultipleSymbolDefinitions;1308 log.debug("strong symbol '{s}' defined multiple times", .{sym_name});
1309 return error.MultipleSymbolDefinitions;
1310 }
1311 continue;
1258 },1312 },
1259 else => {},1313 else => {},
1260 }1314 }
12611315
1262 global.value.tag = .strong;1316 global.value.tag = if (is_weak) .weak else .strong;
1263 global.value.file = object_id;1317 global.value.file = object_id;
1264 global.value.index = @intCast(u32, sym_id);1318 global.value.index = @intCast(u32, sym_id);
1265 } else if (Symbol.isUndef(sym)) {1319 } else if (Symbol.isUndef(sym)) {
...@@ -1340,6 +1394,21 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1340,6 +1394,21 @@ fn resolveSymbols(self: *Zld) !void {
1340 .section = 0,1394 .section = 0,
1341 .file = 0,1395 .file = 0,
1342 });1396 });
1397
1398 {
1399 log.debug("symtab", .{});
1400 for (self.symtab.items()) |sym| {
1401 switch (sym.value.tag) {
1402 .weak, .strong => {
1403 log.debug(" | {s} => {s}", .{ sym.key, self.objects.items[sym.value.file.?].name.? });
1404 },
1405 .import => {
1406 log.debug(" | {s} => libSystem.B.dylib", .{sym.key});
1407 },
1408 else => unreachable,
1409 }
1410 }
1411 }
1343}1412}
13441413
1345fn resolveStubsAndGotEntries(self: *Zld) !void {1414fn resolveStubsAndGotEntries(self: *Zld) !void {
...@@ -1412,9 +1481,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1412,9 +1481,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1412 log.debug("relocating object {s}", .{object.name});1481 log.debug("relocating object {s}", .{object.name});
14131482
1414 for (object.sections.items) |sect, source_sect_id| {1483 for (object.sections.items) |sect, source_sect_id| {
1484 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or
1485 sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue;
1486
1415 const segname = parseName(&sect.inner.segname);1487 const segname = parseName(&sect.inner.segname);
1416 const sectname = parseName(&sect.inner.sectname);1488 const sectname = parseName(&sect.inner.sectname);
14171489
1490 log.debug("relocating section '{s},{s}'", .{ segname, sectname });
1491
1418 // Get mapping1492 // Get mapping
1419 const target_mapping = self.mappings.get(.{1493 const target_mapping = self.mappings.get(.{
1420 .object_id = @intCast(u16, object_id),1494 .object_id = @intCast(u16, object_id),
...@@ -1532,6 +1606,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1532,6 +1606,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1532 target_sect_off,1606 target_sect_off,
1533 target_sect_off + sect.code.len,1607 target_sect_off + sect.code.len,
1534 });1608 });
1609
1535 // Zero-out the space1610 // Zero-out the space
1536 var zeroes = try self.allocator.alloc(u8, sect.code.len);1611 var zeroes = try self.allocator.alloc(u8, sect.code.len);
1537 defer self.allocator.free(zeroes);1612 defer self.allocator.free(zeroes);
...@@ -1571,25 +1646,33 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target)...@@ -1571,25 +1646,33 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target)
1571 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];1646 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1572 const target_addr = target_sect.addr + target_mapping.offset;1647 const target_addr = target_sect.addr + target_mapping.offset;
1573 break :blk sym.n_value - source_sect.addr + target_addr;1648 break :blk sym.n_value - source_sect.addr + target_addr;
1574 } else {1649 } else if (self.symtab.get(sym_name)) |global| {
1575 if (self.stubs.get(sym_name)) |index| {1650 switch (global.tag) {
1576 log.debug(" | symbol stub '{s}'", .{sym_name});1651 .weak, .strong => {
1577 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;1652 log.debug(" | global symbol '{s}'", .{sym_name});
1578 const stubs = segment.sections.items[self.stubs_section_index.?];1653 break :blk global.address;
1579 break :blk stubs.addr + index * stubs.reserved2;1654 },
1580 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {1655 .import => {
1581 log.debug(" | symbol '__tlv_bootstrap'", .{});1656 if (self.stubs.get(sym_name)) |index| {
1582 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1657 log.debug(" | symbol stub '{s}'", .{sym_name});
1583 const tlv = segment.sections.items[self.tlv_section_index.?];1658 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1584 break :blk tlv.addr;1659 const stubs = segment.sections.items[self.stubs_section_index.?];
1585 } else {1660 break :blk stubs.addr + index * stubs.reserved2;
1586 const global = self.symtab.get(sym_name) orelse {1661 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
1587 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});1662 log.debug(" | symbol '__tlv_bootstrap'", .{});
1588 return error.FailedToResolveRelocationTarget;1663 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1589 };1664 const tlv = segment.sections.items[self.tlv_section_index.?];
1590 log.debug(" | global symbol '{s}'", .{sym_name});1665 break :blk tlv.addr;
1591 break :blk global.address;1666 } else {
1667 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1668 return error.FailedToResolveRelocationTarget;
1669 }
1670 },
1671 else => unreachable,
1592 }1672 }
1673 } else {
1674 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1675 return error.FailedToResolveRelocationTarget;
1593 }1676 }
1594 },1677 },
1595 .section => |sect_id| {1678 .section => |sect_id| {
...@@ -2008,6 +2091,12 @@ fn populateMetadata(self: *Zld) !void {...@@ -2008,6 +2091,12 @@ fn populateMetadata(self: *Zld) !void {
2008}2091}
20092092
2010fn flush(self: *Zld) !void {2093fn flush(self: *Zld) !void {
2094 if (self.common_section_index) |index| {
2095 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2096 const sect = &seg.sections.items[index];
2097 sect.offset = 0;
2098 }
2099
2011 if (self.bss_section_index) |index| {2100 if (self.bss_section_index) |index| {
2012 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2101 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2013 const sect = &seg.sections.items[index];2102 const sect = &seg.sections.items[index];
...@@ -2040,6 +2129,24 @@ fn flush(self: *Zld) !void {...@@ -2040,6 +2129,24 @@ fn flush(self: *Zld) !void {
2040 try self.file.?.pwriteAll(buffer, sect.offset);2129 try self.file.?.pwriteAll(buffer, sect.offset);
2041 }2130 }
20422131
2132 if (self.mod_init_func_section_index) |index| {
2133 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2134 const sect = &seg.sections.items[index];
2135
2136 var initializers = std.ArrayList(u64).init(self.allocator);
2137 defer initializers.deinit();
2138
2139 // TODO sort the initializers globally
2140 for (self.objects.items) |object| {
2141 for (object.initializers.items) |initializer| {
2142 try initializers.append(initializer.target_addr);
2143 }
2144 }
2145
2146 _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);
2147 sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));
2148 }
2149
2043 try self.writeGotEntries();2150 try self.writeGotEntries();
2044 try self.setEntryPoint();2151 try self.setEntryPoint();
2045 try self.writeRebaseInfoTable();2152 try self.writeRebaseInfoTable();
...@@ -2139,35 +2246,18 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2139,35 +2246,18 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2139 // TODO audit and investigate this.2246 // TODO audit and investigate this.
2140 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2247 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2141 const sect = seg.sections.items[idx];2248 const sect = seg.sections.items[idx];
2142 const npointers = sect.size * @sizeOf(u64);
2143 const base_offset = sect.addr - seg.inner.vmaddr;2249 const base_offset = sect.addr - seg.inner.vmaddr;
2144 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);2250 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
21452251
2146 try pointers.ensureCapacity(pointers.items.len + npointers);2252 var index: u64 = 0;
2147 var i: usize = 0;2253 for (self.objects.items) |object| {
2148 while (i < npointers) : (i += 1) {2254 for (object.initializers.items) |_| {
2149 pointers.appendAssumeCapacity(.{2255 try pointers.append(.{
2150 .offset = base_offset + i * @sizeOf(u64),2256 .offset = base_offset + index * @sizeOf(u64),
2151 .segment_id = segment_id,2257 .segment_id = segment_id,
2152 });2258 });
2153 }2259 index += 1;
2154 }2260 }
2155
2156 if (self.mod_term_func_section_index) |idx| {
2157 // TODO audit and investigate this.
2158 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2159 const sect = seg.sections.items[idx];
2160 const npointers = sect.size * @sizeOf(u64);
2161 const base_offset = sect.addr - seg.inner.vmaddr;
2162 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
2163
2164 try pointers.ensureCapacity(pointers.items.len + npointers);
2165 var i: usize = 0;
2166 while (i < npointers) : (i += 1) {
2167 pointers.appendAssumeCapacity(.{
2168 .offset = base_offset + i * @sizeOf(u64),
2169 .segment_id = segment_id,
2170 });
2171 }2261 }
2172 }2262 }
21732263
...@@ -2447,7 +2537,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2447,7 +2537,7 @@ fn writeDebugInfo(self: *Zld) !void {
2447 .n_type = macho.N_OSO,2537 .n_type = macho.N_OSO,
2448 .n_sect = 0,2538 .n_sect = 0,
2449 .n_desc = 1,2539 .n_desc = 1,
2450 .n_value = tu_mtime,2540 .n_value = 0, //tu_mtime, TODO figure out why precalculated mtime value doesn't work
2451 });2541 });
24522542
2453 for (object.stabs.items) |stab| {2543 for (object.stabs.items) |stab| {
src/link/MachO/reloc/aarch64.zig+3-1
...@@ -226,7 +226,9 @@ pub const Parser = struct {...@@ -226,7 +226,9 @@ pub const Parser = struct {
226 try parser.parseTlvpLoadPageOff(rel);226 try parser.parseTlvpLoadPageOff(rel);
227 },227 },
228 .ARM64_RELOC_POINTER_TO_GOT => {228 .ARM64_RELOC_POINTER_TO_GOT => {
229 return error.ToDoRelocPointerToGot;229 // TODO Handle pointer to GOT. This reloc seems to appear in
230 // __LD,__compact_unwind section which we currently don't handle.
231 log.debug("Unhandled relocation ARM64_RELOC_POINTER_TO_GOT", .{});
230 },232 },
231 }233 }
232 }234 }
src/main.zig+6
...@@ -355,6 +355,8 @@ const usage_build_generic =...@@ -355,6 +355,8 @@ const usage_build_generic =
355 \\ -rpath [path] Add directory to the runtime library search path355 \\ -rpath [path] Add directory to the runtime library search path
356 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library356 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
357 \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library357 \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library
358 \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries
359 \\ -fno-allow-shlib-undefined Disallows undefined symbols in shared libraries
358 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker360 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
359 \\ --emit-relocs Enable output of relocation sections for post build tools361 \\ --emit-relocs Enable output of relocation sections for post build tools
360 \\ -dynamic Force output to be dynamically linked362 \\ -dynamic Force output to be dynamically linked
...@@ -988,6 +990,10 @@ fn buildOutputType(...@@ -988,6 +990,10 @@ fn buildOutputType(
988 link_eh_frame_hdr = true;990 link_eh_frame_hdr = true;
989 } else if (mem.eql(u8, arg, "--emit-relocs")) {991 } else if (mem.eql(u8, arg, "--emit-relocs")) {
990 link_emit_relocs = true;992 link_emit_relocs = true;
993 } else if (mem.eql(u8, arg, "-fallow-shlib-undefined")) {
994 linker_allow_shlib_undefined = true;
995 } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) {
996 linker_allow_shlib_undefined = false;
991 } else if (mem.eql(u8, arg, "-Bsymbolic")) {997 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
992 linker_bind_global_refs_locally = true;998 linker_bind_global_refs_locally = true;
993 } else if (mem.eql(u8, arg, "--verbose-link")) {999 } else if (mem.eql(u8, arg, "--verbose-link")) {
src/register_manager.zig+74-37
...@@ -36,7 +36,7 @@ pub fn RegisterManager(...@@ -36,7 +36,7 @@ pub fn RegisterManager(
36 }36 }
3737
38 fn isTracked(reg: Register) bool {38 fn isTracked(reg: Register) bool {
39 return std.mem.indexOfScalar(Register, callee_preserved_regs, reg) != null;39 return reg.allocIndex() != null;
40 }40 }
4141
42 fn markRegUsed(self: *Self, reg: Register) void {42 fn markRegUsed(self: *Self, reg: Register) void {
...@@ -55,6 +55,7 @@ pub fn RegisterManager(...@@ -55,6 +55,7 @@ pub fn RegisterManager(
55 self.free_registers |= @as(FreeRegInt, 1) << shift;55 self.free_registers |= @as(FreeRegInt, 1) << shift;
56 }56 }
5757
58 /// Returns true when this register is not tracked
58 pub fn isRegFree(self: Self, reg: Register) bool {59 pub fn isRegFree(self: Self, reg: Register) bool {
59 if (FreeRegInt == u0) return true;60 if (FreeRegInt == u0) return true;
60 const index = reg.allocIndex() orelse return true;61 const index = reg.allocIndex() orelse return true;
...@@ -63,7 +64,8 @@ pub fn RegisterManager(...@@ -63,7 +64,8 @@ pub fn RegisterManager(
63 }64 }
6465
65 /// Returns whether this register was allocated in the course66 /// Returns whether this register was allocated in the course
66 /// of this function67 /// of this function.
68 /// Returns false when this register is not tracked
67 pub fn isRegAllocated(self: Self, reg: Register) bool {69 pub fn isRegAllocated(self: Self, reg: Register) bool {
68 if (FreeRegInt == u0) return false;70 if (FreeRegInt == u0) return false;
69 const index = reg.allocIndex() orelse return false;71 const index = reg.allocIndex() orelse return false;
...@@ -71,57 +73,89 @@ pub fn RegisterManager(...@@ -71,57 +73,89 @@ pub fn RegisterManager(
71 return self.allocated_registers & @as(FreeRegInt, 1) << shift != 0;73 return self.allocated_registers & @as(FreeRegInt, 1) << shift != 0;
72 }74 }
7375
74 /// Before calling, must ensureCapacity + 1 on self.registers.76 /// Before calling, must ensureCapacity + count on self.registers.
75 /// Returns `null` if all registers are allocated.77 /// Returns `null` if all registers are allocated.
76 pub fn tryAllocReg(self: *Self, inst: *ir.Inst) ?Register {78 pub fn tryAllocRegs(self: *Self, comptime count: comptime_int, insts: [count]*ir.Inst) ?[count]Register {
77 const free_index = @ctz(FreeRegInt, self.free_registers);79 if (self.tryAllocRegsWithoutTracking(count)) |regs| {
78 if (free_index >= callee_preserved_regs.len) {80 for (regs) |reg, i| {
81 self.markRegUsed(reg);
82 self.registers.putAssumeCapacityNoClobber(reg, insts[i]);
83 }
84
85 return regs;
86 } else {
79 return null;87 return null;
80 }88 }
89 }
8190
82 // This is necessary because the return type of @ctz is 191 /// Before calling, must ensureCapacity + 1 on self.registers.
83 // bit longer than ShiftInt if callee_preserved_regs.len92 /// Returns `null` if all registers are allocated.
84 // is a power of two. This int cast is always safe because93 pub fn tryAllocReg(self: *Self, inst: *ir.Inst) ?Register {
85 // free_index < callee_preserved_regs.len94 return if (tryAllocRegs(self, 1, .{inst})) |regs| regs[0] else null;
86 const shift = @intCast(ShiftInt, free_index);95 }
87 const mask = @as(FreeRegInt, 1) << shift;
88 self.free_registers &= ~mask;
89 self.allocated_registers |= mask;
9096
91 const reg = callee_preserved_regs[free_index];97 /// Before calling, must ensureCapacity + count on self.registers.
92 self.registers.putAssumeCapacityNoClobber(reg, inst);98 pub fn allocRegs(self: *Self, comptime count: comptime_int, insts: [count]*ir.Inst) ![count]Register {
93 log.debug("alloc {} => {*}", .{ reg, inst });99 comptime assert(count > 0 and count <= callee_preserved_regs.len);
94 return reg;100
101 return self.tryAllocRegs(count, insts) orelse blk: {
102 // We'll take over the first count registers. Spill
103 // the instructions that were previously there to a
104 // stack allocations.
105 var regs: [count]Register = undefined;
106 std.mem.copy(Register, &regs, callee_preserved_regs[0..count]);
107
108 for (regs) |reg, i| {
109 if (self.isRegFree(reg)) {
110 self.markRegUsed(reg);
111 self.registers.putAssumeCapacityNoClobber(reg, insts[i]);
112 } else {
113 const regs_entry = self.registers.getEntry(reg).?;
114 const spilled_inst = regs_entry.value;
115 regs_entry.value = insts[i];
116 try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
117 }
118 }
119
120 break :blk regs;
121 };
95 }122 }
96123
97 /// Before calling, must ensureCapacity + 1 on self.registers.124 /// Before calling, must ensureCapacity + 1 on self.registers.
98 pub fn allocReg(self: *Self, inst: *ir.Inst) !Register {125 pub fn allocReg(self: *Self, inst: *ir.Inst) !Register {
99 return self.tryAllocReg(inst) orelse b: {126 return (try allocRegs(self, 1, .{inst}))[0];
100 // We'll take over the first register. Move the instruction that was previously127 }
101 // there to a stack allocation.
102 const reg = callee_preserved_regs[0];
103 const regs_entry = self.registers.getEntry(reg).?;
104 const spilled_inst = regs_entry.value;
105 regs_entry.value = inst;
106 try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
107128
108 break :b reg;129 /// Does not track the registers.
109 };130 /// Returns `null` if not enough registers are free.
131 pub fn tryAllocRegsWithoutTracking(self: *Self, comptime count: comptime_int) ?[count]Register {
132 comptime if (callee_preserved_regs.len == 0) return null;
133 comptime assert(count > 0 and count <= callee_preserved_regs.len);
134
135 const free_registers = @popCount(FreeRegInt, self.free_registers);
136 if (free_registers < count) return null;
137
138 var regs: [count]Register = undefined;
139 var i: usize = 0;
140 for (callee_preserved_regs) |reg| {
141 if (i >= count) break;
142 if (self.isRegFree(reg)) {
143 regs[i] = reg;
144 i += 1;
145 }
146 }
147 return regs;
110 }148 }
111149
112 /// Does not track the register.150 /// Does not track the register.
113 /// Returns `null` if all registers are allocated.151 /// Returns `null` if all registers are allocated.
114 pub fn findUnusedReg(self: *Self) ?Register {152 pub fn tryAllocRegWithoutTracking(self: *Self) ?Register {
115 const free_index = @ctz(FreeRegInt, self.free_registers);153 return if (tryAllocRegsWithoutTracking(self, 1)) |regs| regs[0] else null;
116 if (free_index >= callee_preserved_regs.len) {
117 return null;
118 }
119 return callee_preserved_regs[free_index];
120 }154 }
121155
122 /// Does not track the register.156 /// Does not track the register.
123 pub fn allocRegWithoutTracking(self: *Self) !Register {157 pub fn allocRegWithoutTracking(self: *Self) !Register {
124 return self.findUnusedReg() orelse b: {158 return self.tryAllocRegWithoutTracking() orelse b: {
125 // We'll take over the first register. Move the instruction that was previously159 // We'll take over the first register. Move the instruction that was previously
126 // there to a stack allocation.160 // there to a stack allocation.
127 const reg = callee_preserved_regs[0];161 const reg = callee_preserved_regs[0];
...@@ -190,7 +224,10 @@ pub fn RegisterManager(...@@ -190,7 +224,10 @@ pub fn RegisterManager(
190}224}
191225
192const MockRegister = enum(u2) {226const MockRegister = enum(u2) {
193 r0, r1, r2, r3,227 r0,
228 r1,
229 r2,
230 r3,
194231
195 pub fn allocIndex(self: MockRegister) ?u2 {232 pub fn allocIndex(self: MockRegister) ?u2 {
196 inline for (mock_callee_preserved_regs) |cpreg, i| {233 inline for (mock_callee_preserved_regs) |cpreg, i| {
...@@ -213,7 +250,7 @@ const MockFunction = struct {...@@ -213,7 +250,7 @@ const MockFunction = struct {
213 self.register_manager.deinit(self.allocator);250 self.register_manager.deinit(self.allocator);
214 self.spilled.deinit(self.allocator);251 self.spilled.deinit(self.allocator);
215 }252 }
216 253
217 pub fn spillInstruction(self: *Self, src: LazySrcLoc, reg: MockRegister, inst: *ir.Inst) !void {254 pub fn spillInstruction(self: *Self, src: LazySrcLoc, reg: MockRegister, inst: *ir.Inst) !void {
218 try self.spilled.append(self.allocator, reg);255 try self.spilled.append(self.allocator, reg);
219 }256 }
src/stage1/bigfloat.cpp+3-6
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9#include "bigint.hpp"9#include "bigint.hpp"
10#include "buffer.hpp"10#include "buffer.hpp"
11#include "softfloat.hpp"11#include "softfloat.hpp"
12#include "softfloat_ext.hpp"
12#include "parse_f128.h"13#include "parse_f128.h"
13#include <stdio.h>14#include <stdio.h>
14#include <math.h>15#include <math.h>
...@@ -60,9 +61,7 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) {...@@ -60,9 +61,7 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) {
6061
61 if (i == 0) {62 if (i == 0) {
62 if (op->is_negative) {63 if (op->is_negative) {
63 float128_t zero_f128;64 f128M_neg(&dest->value, &dest->value);
64 ui32_to_f128M(0, &zero_f128);
65 f128M_sub(&zero_f128, &dest->value, &dest->value);
66 }65 }
67 return;66 return;
68 }67 }
...@@ -89,9 +88,7 @@ void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {...@@ -89,9 +88,7 @@ void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
89}88}
9089
91void bigfloat_negate(BigFloat *dest, const BigFloat *op) {90void bigfloat_negate(BigFloat *dest, const BigFloat *op) {
92 float128_t zero_f128;91 f128M_neg(&op->value, &dest->value);
93 ui32_to_f128M(0, &zero_f128);
94 f128M_sub(&zero_f128, &op->value, &dest->value);
95}92}
9693
97void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {94void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
src/stage1/bigint.cpp+2-2
...@@ -1446,10 +1446,10 @@ void bigint_negate(BigInt *dest, const BigInt *op) {...@@ -1446,10 +1446,10 @@ void bigint_negate(BigInt *dest, const BigInt *op) {
1446 bigint_normalize(dest);1446 bigint_normalize(dest);
1447}1447}
14481448
1449void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count) {1449void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
1450 BigInt zero;1450 BigInt zero;
1451 bigint_init_unsigned(&zero, 0);1451 bigint_init_unsigned(&zero, 0);
1452 bigint_sub_wrap(dest, &zero, op, bit_count, true);1452 bigint_sub_wrap(dest, &zero, op, bit_count, is_signed);
1453}1453}
14541454
1455void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {1455void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
src/stage1/bigint.hpp+1-1
...@@ -75,7 +75,7 @@ void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t...@@ -75,7 +75,7 @@ void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t
75void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2);75void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2);
7676
77void bigint_negate(BigInt *dest, const BigInt *op);77void bigint_negate(BigInt *dest, const BigInt *op);
78void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count);78void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
79void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);79void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
80void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);80void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
8181
src/stage1/codegen.cpp+4-1
...@@ -7436,7 +7436,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n...@@ -7436,7 +7436,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
7436 case ZigTypeIdFloat:7436 case ZigTypeIdFloat:
7437 switch (type_entry->data.floating.bit_count) {7437 switch (type_entry->data.floating.bit_count) {
7438 case 16:7438 case 16:
7439 return LLVMConstReal(get_llvm_type(g, type_entry), zig_f16_to_double(const_val->data.x_f16));7439 {
7440 LLVMValueRef as_int = LLVMConstInt(LLVMInt16Type(), const_val->data.x_f16.v, false);
7441 return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));
7442 }
7440 case 32:7443 case 32:
7441 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32);7444 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32);
7442 case 64:7445 case 64:
src/stage1/ir.cpp+13-20
...@@ -9534,7 +9534,7 @@ static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNo...@@ -9534,7 +9534,7 @@ static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNo
95349534
9535 Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope);9535 Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope);
9536 // purposefully pass null for result_loc and let EndExpr handle it9536 // purposefully pass null for result_loc and let EndExpr handle it
9537 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);9537 return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr);
9538}9538}
95399539
9540static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {9540static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
...@@ -10199,14 +10199,12 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode...@@ -10199,14 +10199,12 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode
10199 }10199 }
1020010200
10201 IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node);10201 IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node);
10202 if (node->data.suspend.block != nullptr) {10202 ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);
10203 ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);10203 Scope *child_scope = &suspend_scope->base;
10204 Scope *child_scope = &suspend_scope->base;10204 IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);
10205 IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);10205 if (susp_res == irb->codegen->invalid_inst_src)
10206 if (susp_res == irb->codegen->invalid_inst_src)10206 return irb->codegen->invalid_inst_src;
10207 return irb->codegen->invalid_inst_src;10207 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
10208 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
10209 }
1021010208
10211 return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin));10209 return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin));
10212}10210}
...@@ -11363,11 +11361,8 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {...@@ -11363,11 +11361,8 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {
11363 } else if (op->type->id == ZigTypeIdFloat) {11361 } else if (op->type->id == ZigTypeIdFloat) {
11364 switch (op->type->data.floating.bit_count) {11362 switch (op->type->data.floating.bit_count) {
11365 case 16:11363 case 16:
11366 {11364 out_val->data.x_f16 = f16_neg(op->data.x_f16);
11367 const float16_t zero = zig_double_to_f16(0);11365 return;
11368 out_val->data.x_f16 = f16_sub(zero, op->data.x_f16);
11369 return;
11370 }
11371 case 32:11366 case 32:
11372 out_val->data.x_f32 = -op->data.x_f32;11367 out_val->data.x_f32 = -op->data.x_f32;
11373 return;11368 return;
...@@ -11375,9 +11370,7 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {...@@ -11375,9 +11370,7 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {
11375 out_val->data.x_f64 = -op->data.x_f64;11370 out_val->data.x_f64 = -op->data.x_f64;
11376 return;11371 return;
11377 case 128:11372 case 128:
11378 float128_t zero_f128;11373 f128M_neg(&op->data.x_f128, &out_val->data.x_f128);
11379 ui32_to_f128M(0, &zero_f128);
11380 f128M_sub(&zero_f128, &op->data.x_f128, &out_val->data.x_f128);
11381 return;11374 return;
11382 default:11375 default:
11383 zig_unreachable();11376 zig_unreachable();
...@@ -21665,8 +21658,8 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z...@@ -21665,8 +21658,8 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z
21665{21658{
21666 bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat);21659 bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat);
2166721660
21668 bool ok_type = ((scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) ||21661 bool ok_type = scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdComptimeInt ||
21669 scalar_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op));21662 (is_float && !is_wrap_op);
2167021663
21671 if (!ok_type) {21664 if (!ok_type) {
21672 const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";21665 const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
...@@ -21677,7 +21670,7 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z...@@ -21677,7 +21670,7 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z
21677 float_negate(scalar_out_val, operand_val);21670 float_negate(scalar_out_val, operand_val);
21678 } else if (is_wrap_op) {21671 } else if (is_wrap_op) {
21679 bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint,21672 bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint,
21680 scalar_type->data.integral.bit_count);21673 scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
21681 } else {21674 } else {
21682 bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint);21675 bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint);
21683 }21676 }
src/stage1/parser.cpp+1-4
...@@ -946,10 +946,7 @@ static AstNode *ast_parse_statement(ParseContext *pc) {...@@ -946,10 +946,7 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
946946
947 Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);947 Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);
948 if (suspend != nullptr) {948 if (suspend != nullptr) {
949 AstNode *statement = nullptr;949 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
950 if (eat_token_if(pc, TokenIdSemicolon) == nullptr)
951 statement = ast_expect(pc, ast_parse_block_expr_statement);
952
953 AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);950 AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);
954 res->data.suspend.block = statement;951 res->data.suspend.block = statement;
955 return res;952 return res;
src/stage1/softfloat_ext.cpp+31-7
...@@ -1,17 +1,21 @@...@@ -1,17 +1,21 @@
1#include "softfloat_ext.hpp"1#include "softfloat_ext.hpp"
2#include "zigendian.h"
23
3extern "C" {4extern "C" {
4 #include "softfloat.h"5 #include "softfloat.h"
5}6}
67
7void f128M_abs(const float128_t *aPtr, float128_t *zPtr) {8void f128M_abs(const float128_t *aPtr, float128_t *zPtr) {
8 float128_t zero_float;9 // Clear the sign bit.
9 ui32_to_f128M(0, &zero_float);10#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
10 if (f128M_lt(aPtr, &zero_float)) {11 zPtr->v[1] = aPtr->v[1] & ~(UINT64_C(1) << 63);
11 f128M_sub(&zero_float, aPtr, zPtr);12 zPtr->v[0] = aPtr->v[0];
12 } else {13#elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
13 *zPtr = *aPtr;14 zPtr->v[0] = aPtr->v[0] & ~(UINT64_C(1) << 63);
14 } 15 zPtr->v[1] = aPtr->v[1];
16#else
17#error Unsupported endian
18#endif
15}19}
1620
17void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {21void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
...@@ -22,4 +26,24 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {...@@ -22,4 +26,24 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
22 } else {26 } else {
23 f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr);27 f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
24 } 28 }
29}
30
31float16_t f16_neg(const float16_t a) {
32 union { uint16_t ui; float16_t f; } uA;
33 // Toggle the sign bit.
34 uA.ui = a.v ^ (UINT16_C(1) << 15);
35 return uA.f;
36}
37
38void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {
39 // Toggle the sign bit.
40#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
41 zPtr->v[1] = aPtr->v[1] ^ (UINT64_C(1) << 63);
42 zPtr->v[0] = aPtr->v[0];
43#elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
44 zPtr->v[0] = aPtr->v[0] ^ (UINT64_C(1) << 63);
45 zPtr->v[1] = aPtr->v[1];
46#else
47#error Unsupported endian
48#endif
25}49}
\ No newline at end of file
src/stage1/softfloat_ext.hpp+3
...@@ -5,5 +5,8 @@...@@ -5,5 +5,8 @@
55
6void f128M_abs(const float128_t *aPtr, float128_t *zPtr);6void f128M_abs(const float128_t *aPtr, float128_t *zPtr);
7void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);7void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);
8void f128M_neg(const float128_t *aPtr, float128_t *zPtr);
9
10float16_t f16_neg(const float16_t a);
811
9#endif12#endif
\ No newline at end of file
src/translate_c.zig+10-6
...@@ -1353,10 +1353,14 @@ fn transCreatePointerArithmeticSignedOp(...@@ -1353,10 +1353,14 @@ fn transCreatePointerArithmeticSignedOp(
13531353
1354 const bitcast_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);1354 const bitcast_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
13551355
1356 const arith_args = .{ .lhs = lhs_node, .rhs = bitcast_node };1356 return transCreateNodeInfixOp(
1357 const arith_node = try if (is_add) Tag.add.create(c.arena, arith_args) else Tag.sub.create(c.arena, arith_args);1357 c,
13581358 scope,
1359 return maybeSuppressResult(c, scope, result_used, arith_node);1359 if (is_add) .add else .sub,
1360 lhs_node,
1361 bitcast_node,
1362 result_used,
1363 );
1360}1364}
13611365
1362fn transBinaryOperator(1366fn transBinaryOperator(
...@@ -2161,8 +2165,8 @@ fn transCCast(...@@ -2161,8 +2165,8 @@ fn transCCast(
2161 return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });2165 return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
2162 }2166 }
2163 if (cIsEnum(dst_type)) {2167 if (cIsEnum(dst_type)) {
2164 // @intToEnum(dest_type, val)2168 // import("std").meta.cast(dest_type, val)
2165 return Tag.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr });2169 return Tag.std_meta_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
2166 }2170 }
2167 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {2171 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {
2168 // @enumToInt(val)2172 // @enumToInt(val)
src/translate_c/ast.zig+3-3
...@@ -1665,7 +1665,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1665,7 +1665,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1665 },1665 },
1666 .array_access => {1666 .array_access => {
1667 const payload = node.castTag(.array_access).?.data;1667 const payload = node.castTag(.array_access).?.data;
1668 const lhs = try renderNode(c, payload.lhs);1668 const lhs = try renderNodeGrouped(c, payload.lhs);
1669 const l_bracket = try c.addToken(.l_bracket, "[");1669 const l_bracket = try c.addToken(.l_bracket, "[");
1670 const index_expr = try renderNode(c, payload.rhs);1670 const index_expr = try renderNode(c, payload.rhs);
1671 _ = try c.addToken(.r_bracket, "]");1671 _ = try c.addToken(.r_bracket, "]");
...@@ -1728,7 +1728,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1728,7 +1728,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1728 },1728 },
1729 .field_access => {1729 .field_access => {
1730 const payload = node.castTag(.field_access).?.data;1730 const payload = node.castTag(.field_access).?.data;
1731 const lhs = try renderNode(c, payload.lhs);1731 const lhs = try renderNodeGrouped(c, payload.lhs);
1732 return renderFieldAccess(c, lhs, payload.field_name);1732 return renderFieldAccess(c, lhs, payload.field_name);
1733 },1733 },
1734 .@"struct", .@"union" => return renderRecord(c, node),1734 .@"struct", .@"union" => return renderRecord(c, node),
...@@ -2073,7 +2073,7 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn...@@ -2073,7 +2073,7 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn
2073 .main_token = l_bracket,2073 .main_token = l_bracket,
2074 .data = .{2074 .data = .{
2075 .lhs = len_expr,2075 .lhs = len_expr,
2076 .rhs = try c.addExtra(std.zig.ast.Node.ArrayTypeSentinel {2076 .rhs = try c.addExtra(std.zig.ast.Node.ArrayTypeSentinel{
2077 .sentinel = sentinel_expr,2077 .sentinel = sentinel_expr,
2078 .elem_type = elem_type_expr,2078 .elem_type = elem_type_expr,
2079 }),2079 }),
test/compile_errors.zig+7-7
...@@ -1021,7 +1021,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1021,7 +1021,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1021 \\export fn entry() void {1021 \\export fn entry() void {
1022 \\ nosuspend {1022 \\ nosuspend {
1023 \\ const bar = async foo();1023 \\ const bar = async foo();
1024 \\ suspend;1024 \\ suspend {}
1025 \\ resume bar;1025 \\ resume bar;
1026 \\ }1026 \\ }
1027 \\}1027 \\}
...@@ -2120,7 +2120,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2120,7 +2120,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2120 \\ non_async_fn = func;2120 \\ non_async_fn = func;
2121 \\}2121 \\}
2122 \\fn func() void {2122 \\fn func() void {
2123 \\ suspend;2123 \\ suspend {}
2124 \\}2124 \\}
2125 , &[_][]const u8{2125 , &[_][]const u8{
2126 "tmp.zig:5:1: error: 'func' cannot be async",2126 "tmp.zig:5:1: error: 'func' cannot be async",
...@@ -2198,7 +2198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2198,7 +2198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2198 \\ var x: anyframe = &f;2198 \\ var x: anyframe = &f;
2199 \\}2199 \\}
2200 \\fn func() void {2200 \\fn func() void {
2201 \\ suspend;2201 \\ suspend {}
2202 \\}2202 \\}
2203 , &[_][]const u8{2203 , &[_][]const u8{
2204 "tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'",2204 "tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'",
...@@ -2231,10 +2231,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2231,10 +2231,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2231 \\ frame = async bar();2231 \\ frame = async bar();
2232 \\}2232 \\}
2233 \\fn foo() void {2233 \\fn foo() void {
2234 \\ suspend;2234 \\ suspend {}
2235 \\}2235 \\}
2236 \\fn bar() void {2236 \\fn bar() void {
2237 \\ suspend;2237 \\ suspend {}
2238 \\}2238 \\}
2239 , &[_][]const u8{2239 , &[_][]const u8{
2240 "tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'",2240 "tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'",
...@@ -2269,7 +2269,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2269,7 +2269,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2269 \\ var result = await frame;2269 \\ var result = await frame;
2270 \\}2270 \\}
2271 \\fn func() void {2271 \\fn func() void {
2272 \\ suspend;2272 \\ suspend {}
2273 \\}2273 \\}
2274 , &[_][]const u8{2274 , &[_][]const u8{
2275 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",2275 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
...@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2347 \\ bar();2347 \\ bar();
2348 \\}2348 \\}
2349 \\fn bar() void {2349 \\fn bar() void {
2350 \\ suspend;2350 \\ suspend {}
2351 \\}2351 \\}
2352 , &[_][]const u8{2352 , &[_][]const u8{
2353 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",2353 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
test/run_translated_c.zig+23
...@@ -1453,4 +1453,27 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1453,4 +1453,27 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1453 \\ return 0;1453 \\ return 0;
1454 \\}1454 \\}
1455 , "");1455 , "");
1456
1457 cases.add("Cast to enum from larger integral type. Issue #6011",
1458 \\#include <stdint.h>
1459 \\#include <stdlib.h>
1460 \\enum Foo { A, B, C };
1461 \\static inline enum Foo do_stuff(void) {
1462 \\ int64_t i = 1;
1463 \\ return (enum Foo)i;
1464 \\}
1465 \\int main(void) {
1466 \\ if (do_stuff() != B) abort();
1467 \\ return 0;
1468 \\}
1469 , "");
1470
1471 cases.add("Render array LHS as grouped node if necessary",
1472 \\#include <stdlib.h>
1473 \\int main(void) {
1474 \\ int arr[] = {40, 41, 42, 43};
1475 \\ if ((arr + 1)[1] != 42) abort();
1476 \\ return 0;
1477 \\}
1478 , "");
1456}1479}
test/runtime_safety.zig+17-17
...@@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
1313
14 cases.addRuntimeSafety("switch on corrupted enum value",14 cases.addRuntimeSafety("switch on corrupted enum value",
15 \\const std = @import("std");15 \\const std = @import("std");
16 ++ check_panic_msg ++16 ++ check_panic_msg ++
17 \\const E = enum(u32) {17 \\const E = enum(u32) {
18 \\ X = 1,18 \\ X = 1,
19 \\};19 \\};
...@@ -28,7 +28,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -28,7 +28,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
2828
29 cases.addRuntimeSafety("switch on corrupted union value",29 cases.addRuntimeSafety("switch on corrupted union value",
30 \\const std = @import("std");30 \\const std = @import("std");
31 ++ check_panic_msg ++31 ++ check_panic_msg ++
32 \\const U = union(enum(u32)) {32 \\const U = union(enum(u32)) {
33 \\ X: u8,33 \\ X: u8,
34 \\};34 \\};
...@@ -54,7 +54,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -54,7 +54,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
5454
55 cases.addRuntimeSafety("@tagName on corrupted enum value",55 cases.addRuntimeSafety("@tagName on corrupted enum value",
56 \\const std = @import("std");56 \\const std = @import("std");
57 ++ check_panic_msg ++57 ++ check_panic_msg ++
58 \\const E = enum(u32) {58 \\const E = enum(u32) {
59 \\ X = 1,59 \\ X = 1,
60 \\};60 \\};
...@@ -67,7 +67,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -67,7 +67,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
6767
68 cases.addRuntimeSafety("@tagName on corrupted union value",68 cases.addRuntimeSafety("@tagName on corrupted union value",
69 \\const std = @import("std");69 \\const std = @import("std");
70 ++ check_panic_msg ++70 ++ check_panic_msg ++
71 \\const U = union(enum(u32)) {71 \\const U = union(enum(u32)) {
72 \\ X: u8,72 \\ X: u8,
73 \\};73 \\};
...@@ -92,7 +92,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -92,7 +92,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
9292
93 cases.addRuntimeSafety("slicing operator with sentinel",93 cases.addRuntimeSafety("slicing operator with sentinel",
94 \\const std = @import("std");94 \\const std = @import("std");
95 ++ check_panic_msg ++95 ++ check_panic_msg ++
96 \\pub fn main() void {96 \\pub fn main() void {
97 \\ var buf = [4]u8{'a','b','c',0};97 \\ var buf = [4]u8{'a','b','c',0};
98 \\ const slice = buf[0..4 :0];98 \\ const slice = buf[0..4 :0];
...@@ -100,7 +100,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -100,7 +100,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
100 );100 );
101 cases.addRuntimeSafety("slicing operator with sentinel",101 cases.addRuntimeSafety("slicing operator with sentinel",
102 \\const std = @import("std");102 \\const std = @import("std");
103 ++ check_panic_msg ++103 ++ check_panic_msg ++
104 \\pub fn main() void {104 \\pub fn main() void {
105 \\ var buf = [4]u8{'a','b','c',0};105 \\ var buf = [4]u8{'a','b','c',0};
106 \\ const slice = buf[0..:0];106 \\ const slice = buf[0..:0];
...@@ -108,7 +108,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -108,7 +108,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
108 );108 );
109 cases.addRuntimeSafety("slicing operator with sentinel",109 cases.addRuntimeSafety("slicing operator with sentinel",
110 \\const std = @import("std");110 \\const std = @import("std");
111 ++ check_panic_msg ++111 ++ check_panic_msg ++
112 \\pub fn main() void {112 \\pub fn main() void {
113 \\ var buf_zero = [0]u8{};113 \\ var buf_zero = [0]u8{};
114 \\ const slice = buf_zero[0..0 :0];114 \\ const slice = buf_zero[0..0 :0];
...@@ -116,7 +116,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -116,7 +116,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
116 );116 );
117 cases.addRuntimeSafety("slicing operator with sentinel",117 cases.addRuntimeSafety("slicing operator with sentinel",
118 \\const std = @import("std");118 \\const std = @import("std");
119 ++ check_panic_msg ++119 ++ check_panic_msg ++
120 \\pub fn main() void {120 \\pub fn main() void {
121 \\ var buf_zero = [0]u8{};121 \\ var buf_zero = [0]u8{};
122 \\ const slice = buf_zero[0..:0];122 \\ const slice = buf_zero[0..:0];
...@@ -124,7 +124,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -124,7 +124,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
124 );124 );
125 cases.addRuntimeSafety("slicing operator with sentinel",125 cases.addRuntimeSafety("slicing operator with sentinel",
126 \\const std = @import("std");126 \\const std = @import("std");
127 ++ check_panic_msg ++127 ++ check_panic_msg ++
128 \\pub fn main() void {128 \\pub fn main() void {
129 \\ var buf_sentinel = [2:0]u8{'a','b'};129 \\ var buf_sentinel = [2:0]u8{'a','b'};
130 \\ @ptrCast(*[3]u8, &buf_sentinel)[2] = 0;130 \\ @ptrCast(*[3]u8, &buf_sentinel)[2] = 0;
...@@ -133,7 +133,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -133,7 +133,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
133 );133 );
134 cases.addRuntimeSafety("slicing operator with sentinel",134 cases.addRuntimeSafety("slicing operator with sentinel",
135 \\const std = @import("std");135 \\const std = @import("std");
136 ++ check_panic_msg ++136 ++ check_panic_msg ++
137 \\pub fn main() void {137 \\pub fn main() void {
138 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };138 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };
139 \\ const slice = buf_slice[0..3 :0];139 \\ const slice = buf_slice[0..3 :0];
...@@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
141 );141 );
142 cases.addRuntimeSafety("slicing operator with sentinel",142 cases.addRuntimeSafety("slicing operator with sentinel",
143 \\const std = @import("std");143 \\const std = @import("std");
144 ++ check_panic_msg ++144 ++ check_panic_msg ++
145 \\pub fn main() void {145 \\pub fn main() void {
146 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };146 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };
147 \\ const slice = buf_slice[0.. :0];147 \\ const slice = buf_slice[0.. :0];
...@@ -367,7 +367,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -367,7 +367,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
367 \\}367 \\}
368 \\fn add(a: i32, b: i32) i32 {368 \\fn add(a: i32, b: i32) i32 {
369 \\ if (a > 100) {369 \\ if (a > 100) {
370 \\ suspend;370 \\ suspend {}
371 \\ }371 \\ }
372 \\ return a + b;372 \\ return a + b;
373 \\}373 \\}
...@@ -407,7 +407,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -407,7 +407,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
407 \\ var frame = @asyncCall(&bytes, {}, ptr, .{});407 \\ var frame = @asyncCall(&bytes, {}, ptr, .{});
408 \\}408 \\}
409 \\fn other() callconv(.Async) void {409 \\fn other() callconv(.Async) void {
410 \\ suspend;410 \\ suspend {}
411 \\}411 \\}
412 );412 );
413413
...@@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
424 \\ await frame;424 \\ await frame;
425 \\}425 \\}
426 \\fn other() void {426 \\fn other() void {
427 \\ suspend;427 \\ suspend {}
428 \\}428 \\}
429 );429 );
430430
...@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
440 \\ other();440 \\ other();
441 \\}441 \\}
442 \\fn other() void {442 \\fn other() void {
443 \\ suspend;443 \\ suspend {}
444 \\}444 \\}
445 );445 );
446446
...@@ -454,7 +454,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -454,7 +454,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
454 \\ resume p; //bad454 \\ resume p; //bad
455 \\}455 \\}
456 \\fn suspendOnce() void {456 \\fn suspendOnce() void {
457 \\ suspend;457 \\ suspend {}
458 \\}458 \\}
459 );459 );
460460
...@@ -1019,7 +1019,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -1019,7 +1019,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
1019 \\}1019 \\}
1020 \\1020 \\
1021 \\fn failing() anyerror!void {1021 \\fn failing() anyerror!void {
1022 \\ suspend;1022 \\ suspend {}
1023 \\ return second();1023 \\ return second();
1024 \\}1024 \\}
1025 \\1025 \\
test/stage1/behavior/async_fn.zig+42-42
...@@ -18,9 +18,9 @@ test "simple coroutine suspend and resume" {...@@ -18,9 +18,9 @@ test "simple coroutine suspend and resume" {
18}18}
19fn simpleAsyncFn() void {19fn simpleAsyncFn() void {
20 global_x += 1;20 global_x += 1;
21 suspend;21 suspend {}
22 global_x += 1;22 global_x += 1;
23 suspend;23 suspend {}
24 global_x += 1;24 global_x += 1;
25}25}
2626
...@@ -34,7 +34,7 @@ test "pass parameter to coroutine" {...@@ -34,7 +34,7 @@ test "pass parameter to coroutine" {
34}34}
35fn simpleAsyncFnWithArg(delta: i32) void {35fn simpleAsyncFnWithArg(delta: i32) void {
36 global_y += delta;36 global_y += delta;
37 suspend;37 suspend {}
38 global_y += delta;38 global_y += delta;
39}39}
4040
...@@ -50,7 +50,7 @@ test "suspend at end of function" {...@@ -50,7 +50,7 @@ test "suspend at end of function" {
5050
51 fn suspendAtEnd() void {51 fn suspendAtEnd() void {
52 x += 1;52 x += 1;
53 suspend;53 suspend {}
54 }54 }
55 };55 };
56 S.doTheTest();56 S.doTheTest();
...@@ -74,11 +74,11 @@ test "local variable in async function" {...@@ -74,11 +74,11 @@ test "local variable in async function" {
7474
75 fn add(a: i32, b: i32) void {75 fn add(a: i32, b: i32) void {
76 var accum: i32 = 0;76 var accum: i32 = 0;
77 suspend;77 suspend {}
78 accum += a;78 accum += a;
79 suspend;79 suspend {}
80 accum += b;80 accum += b;
81 suspend;81 suspend {}
82 x = accum;82 x = accum;
83 }83 }
84 };84 };
...@@ -102,7 +102,7 @@ test "calling an inferred async function" {...@@ -102,7 +102,7 @@ test "calling an inferred async function" {
102 }102 }
103 fn other() void {103 fn other() void {
104 other_frame = @frame();104 other_frame = @frame();
105 suspend;105 suspend {}
106 x += 1;106 x += 1;
107 }107 }
108 };108 };
...@@ -129,7 +129,7 @@ test "@frameSize" {...@@ -129,7 +129,7 @@ test "@frameSize" {
129 }129 }
130 fn other(param: i32) void {130 fn other(param: i32) void {
131 var local: i32 = undefined;131 var local: i32 = undefined;
132 suspend;132 suspend {}
133 }133 }
134 };134 };
135 S.doTheTest();135 S.doTheTest();
...@@ -269,7 +269,7 @@ test "async function with dot syntax" {...@@ -269,7 +269,7 @@ test "async function with dot syntax" {
269 var y: i32 = 1;269 var y: i32 = 1;
270 fn foo() callconv(.Async) void {270 fn foo() callconv(.Async) void {
271 y += 1;271 y += 1;
272 suspend;272 suspend {}
273 }273 }
274 };274 };
275 const p = async S.foo();275 const p = async S.foo();
...@@ -298,7 +298,7 @@ fn doTheAwait(f: anyframe->void) void {...@@ -298,7 +298,7 @@ fn doTheAwait(f: anyframe->void) void {
298fn simpleAsyncFn2(y: *i32) callconv(.Async) void {298fn simpleAsyncFn2(y: *i32) callconv(.Async) void {
299 defer y.* += 2;299 defer y.* += 2;
300 y.* += 1;300 y.* += 1;
301 suspend;301 suspend {}
302}302}
303303
304test "@asyncCall with return type" {304test "@asyncCall with return type" {
...@@ -312,7 +312,7 @@ test "@asyncCall with return type" {...@@ -312,7 +312,7 @@ test "@asyncCall with return type" {
312312
313 fn afunc() i32 {313 fn afunc() i32 {
314 global_frame = @frame();314 global_frame = @frame();
315 suspend;315 suspend {}
316 return 1234;316 return 1234;
317 }317 }
318 };318 };
...@@ -348,7 +348,7 @@ test "async fn with inferred error set" {...@@ -348,7 +348,7 @@ test "async fn with inferred error set" {
348348
349 fn failing() !void {349 fn failing() !void {
350 global_frame = @frame();350 global_frame = @frame();
351 suspend;351 suspend {}
352 return error.Fail;352 return error.Fail;
353 }353 }
354 };354 };
...@@ -375,7 +375,7 @@ fn nonFailing() (anyframe->anyerror!void) {...@@ -375,7 +375,7 @@ fn nonFailing() (anyframe->anyerror!void) {
375 return &Static.frame;375 return &Static.frame;
376}376}
377fn suspendThenFail() callconv(.Async) anyerror!void {377fn suspendThenFail() callconv(.Async) anyerror!void {
378 suspend;378 suspend {}
379 return error.Fail;379 return error.Fail;
380}380}
381fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {381fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {
...@@ -400,7 +400,7 @@ fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {...@@ -400,7 +400,7 @@ fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {
400 resume @frame();400 resume @frame();
401 }401 }
402 my_result.* += 1;402 my_result.* += 1;
403 suspend;403 suspend {}
404 my_result.* += 1;404 my_result.* += 1;
405}405}
406406
...@@ -421,7 +421,7 @@ test "heap allocated async function frame" {...@@ -421,7 +421,7 @@ test "heap allocated async function frame" {
421421
422 fn someFunc() void {422 fn someFunc() void {
423 x += 1;423 x += 1;
424 suspend;424 suspend {}
425 x += 1;425 x += 1;
426 }426 }
427 };427 };
...@@ -454,7 +454,7 @@ test "async function call return value" {...@@ -454,7 +454,7 @@ test "async function call return value" {
454454
455 fn other(x: i32, y: i32) Point {455 fn other(x: i32, y: i32) Point {
456 frame = @frame();456 frame = @frame();
457 suspend;457 suspend {}
458 return Point{458 return Point{
459 .x = x,459 .x = x,
460 .y = y,460 .y = y,
...@@ -487,7 +487,7 @@ test "suspension points inside branching control flow" {...@@ -487,7 +487,7 @@ test "suspension points inside branching control flow" {
487487
488 fn func(b: bool) void {488 fn func(b: bool) void {
489 while (b) {489 while (b) {
490 suspend;490 suspend {}
491 result += 1;491 result += 1;
492 }492 }
493 }493 }
...@@ -541,7 +541,7 @@ test "pass string literal to async function" {...@@ -541,7 +541,7 @@ test "pass string literal to async function" {
541541
542 fn hello(msg: []const u8) void {542 fn hello(msg: []const u8) void {
543 frame = @frame();543 frame = @frame();
544 suspend;544 suspend {}
545 expectEqualStrings("hello", msg);545 expectEqualStrings("hello", msg);
546 ok = true;546 ok = true;
547 }547 }
...@@ -566,7 +566,7 @@ test "await inside an errdefer" {...@@ -566,7 +566,7 @@ test "await inside an errdefer" {
566566
567 fn func() void {567 fn func() void {
568 frame = @frame();568 frame = @frame();
569 suspend;569 suspend {}
570 }570 }
571 };571 };
572 S.doTheTest();572 S.doTheTest();
...@@ -590,7 +590,7 @@ test "try in an async function with error union and non-zero-bit payload" {...@@ -590,7 +590,7 @@ test "try in an async function with error union and non-zero-bit payload" {
590590
591 fn theProblem() ![]u8 {591 fn theProblem() ![]u8 {
592 frame = @frame();592 frame = @frame();
593 suspend;593 suspend {}
594 const result = try other();594 const result = try other();
595 return result;595 return result;
596 }596 }
...@@ -622,7 +622,7 @@ test "returning a const error from async function" {...@@ -622,7 +622,7 @@ test "returning a const error from async function" {
622622
623 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {623 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
624 frame = @frame();624 frame = @frame();
625 suspend;625 suspend {}
626 ok = true;626 ok = true;
627 return error.OutOfMemory;627 return error.OutOfMemory;
628 }628 }
...@@ -967,7 +967,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {...@@ -967,7 +967,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
967967
968 fn failing() !void {968 fn failing() !void {
969 global_frame = @frame();969 global_frame = @frame();
970 suspend;970 suspend {}
971 return error.Fail;971 return error.Fail;
972 }972 }
973 };973 };
...@@ -977,7 +977,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {...@@ -977,7 +977,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
977test "@asyncCall with actual frame instead of byte buffer" {977test "@asyncCall with actual frame instead of byte buffer" {
978 const S = struct {978 const S = struct {
979 fn func() i32 {979 fn func() i32 {
980 suspend;980 suspend {}
981 return 1234;981 return 1234;
982 }982 }
983 };983 };
...@@ -993,7 +993,7 @@ test "@asyncCall using the result location inside the frame" {...@@ -993,7 +993,7 @@ test "@asyncCall using the result location inside the frame" {
993 fn simple2(y: *i32) callconv(.Async) i32 {993 fn simple2(y: *i32) callconv(.Async) i32 {
994 defer y.* += 2;994 defer y.* += 2;
995 y.* += 1;995 y.* += 1;
996 suspend;996 suspend {}
997 return 1234;997 return 1234;
998 }998 }
999 fn getAnswer(f: anyframe->i32, out: *i32) void {999 fn getAnswer(f: anyframe->i32, out: *i32) void {
...@@ -1095,7 +1095,7 @@ test "nosuspend function call" {...@@ -1095,7 +1095,7 @@ test "nosuspend function call" {
1095 }1095 }
1096 fn add(a: i32, b: i32) i32 {1096 fn add(a: i32, b: i32) i32 {
1097 if (a > 100) {1097 if (a > 100) {
1098 suspend;1098 suspend {}
1099 }1099 }
1100 return a + b;1100 return a + b;
1101 }1101 }
...@@ -1170,7 +1170,7 @@ test "suspend in for loop" {...@@ -1170,7 +1170,7 @@ test "suspend in for loop" {
1170 global_frame = @frame();1170 global_frame = @frame();
1171 var sum: u32 = 0;1171 var sum: u32 = 0;
1172 for (stuff) |x| {1172 for (stuff) |x| {
1173 suspend;1173 suspend {}
1174 sum += x;1174 sum += x;
1175 }1175 }
1176 global_frame = null;1176 global_frame = null;
...@@ -1197,7 +1197,7 @@ test "suspend in while loop" {...@@ -1197,7 +1197,7 @@ test "suspend in while loop" {
1197 global_frame = @frame();1197 global_frame = @frame();
1198 defer global_frame = null;1198 defer global_frame = null;
1199 while (stuff) |val| {1199 while (stuff) |val| {
1200 suspend;1200 suspend {}
1201 return val;1201 return val;
1202 }1202 }
1203 return 0;1203 return 0;
...@@ -1206,7 +1206,7 @@ test "suspend in while loop" {...@@ -1206,7 +1206,7 @@ test "suspend in while loop" {
1206 global_frame = @frame();1206 global_frame = @frame();
1207 defer global_frame = null;1207 defer global_frame = null;
1208 while (stuff) |val| {1208 while (stuff) |val| {
1209 suspend;1209 suspend {}
1210 return val;1210 return val;
1211 } else |err| {1211 } else |err| {
1212 return 0;1212 return 0;
...@@ -1339,7 +1339,7 @@ test "async function passed 0-bit arg after non-0-bit arg" {...@@ -1339,7 +1339,7 @@ test "async function passed 0-bit arg after non-0-bit arg" {
13391339
1340 fn bar(x: i32, args: anytype) anyerror!void {1340 fn bar(x: i32, args: anytype) anyerror!void {
1341 global_frame = @frame();1341 global_frame = @frame();
1342 suspend;1342 suspend {}
1343 global_int = x;1343 global_int = x;
1344 }1344 }
1345 };1345 };
...@@ -1361,7 +1361,7 @@ test "async function passed align(16) arg after align(8) arg" {...@@ -1361,7 +1361,7 @@ test "async function passed align(16) arg after align(8) arg" {
1361 fn bar(x: u64, args: anytype) anyerror!void {1361 fn bar(x: u64, args: anytype) anyerror!void {
1362 expect(x == 10);1362 expect(x == 10);
1363 global_frame = @frame();1363 global_frame = @frame();
1364 suspend;1364 suspend {}
1365 global_int = args[0];1365 global_int = args[0];
1366 }1366 }
1367 };1367 };
...@@ -1383,7 +1383,7 @@ test "async function call resolves target fn frame, comptime func" {...@@ -1383,7 +1383,7 @@ test "async function call resolves target fn frame, comptime func" {
13831383
1384 fn bar() anyerror!void {1384 fn bar() anyerror!void {
1385 global_frame = @frame();1385 global_frame = @frame();
1386 suspend;1386 suspend {}
1387 global_int += 1;1387 global_int += 1;
1388 }1388 }
1389 };1389 };
...@@ -1406,7 +1406,7 @@ test "async function call resolves target fn frame, runtime func" {...@@ -1406,7 +1406,7 @@ test "async function call resolves target fn frame, runtime func" {
14061406
1407 fn bar() anyerror!void {1407 fn bar() anyerror!void {
1408 global_frame = @frame();1408 global_frame = @frame();
1409 suspend;1409 suspend {}
1410 global_int += 1;1410 global_int += 1;
1411 }1411 }
1412 };1412 };
...@@ -1430,7 +1430,7 @@ test "properly spill optional payload capture value" {...@@ -1430,7 +1430,7 @@ test "properly spill optional payload capture value" {
14301430
1431 fn bar() void {1431 fn bar() void {
1432 global_frame = @frame();1432 global_frame = @frame();
1433 suspend;1433 suspend {}
1434 global_int += 1;1434 global_int += 1;
1435 }1435 }
1436 };1436 };
...@@ -1466,13 +1466,13 @@ test "handle defer interfering with return value spill" {...@@ -1466,13 +1466,13 @@ test "handle defer interfering with return value spill" {
14661466
1467 fn bar() anyerror!void {1467 fn bar() anyerror!void {
1468 global_frame1 = @frame();1468 global_frame1 = @frame();
1469 suspend;1469 suspend {}
1470 return error.Bad;1470 return error.Bad;
1471 }1471 }
14721472
1473 fn baz() void {1473 fn baz() void {
1474 global_frame2 = @frame();1474 global_frame2 = @frame();
1475 suspend;1475 suspend {}
1476 baz_happened = true;1476 baz_happened = true;
1477 }1477 }
1478 };1478 };
...@@ -1497,7 +1497,7 @@ test "take address of temporary async frame" {...@@ -1497,7 +1497,7 @@ test "take address of temporary async frame" {
14971497
1498 fn foo(arg: i32) i32 {1498 fn foo(arg: i32) i32 {
1499 global_frame = @frame();1499 global_frame = @frame();
1500 suspend;1500 suspend {}
1501 return arg + 1234;1501 return arg + 1234;
1502 }1502 }
15031503
...@@ -1520,7 +1520,7 @@ test "nosuspend await" {...@@ -1520,7 +1520,7 @@ test "nosuspend await" {
15201520
1521 fn foo(want_suspend: bool) i32 {1521 fn foo(want_suspend: bool) i32 {
1522 if (want_suspend) {1522 if (want_suspend) {
1523 suspend;1523 suspend {}
1524 }1524 }
1525 return 42;1525 return 42;
1526 }1526 }
...@@ -1569,11 +1569,11 @@ test "nosuspend on async function calls" {...@@ -1569,11 +1569,11 @@ test "nosuspend on async function calls" {
1569// };1569// };
1570// const S1 = struct {1570// const S1 = struct {
1571// fn c() S0 {1571// fn c() S0 {
1572// suspend;1572// suspend {}
1573// return S0{};1573// return S0{};
1574// }1574// }
1575// fn d() !S0 {1575// fn d() !S0 {
1576// suspend;1576// suspend {}
1577// return S0{};1577// return S0{};
1578// }1578// }
1579// };1579// };
...@@ -1591,11 +1591,11 @@ test "nosuspend resume async function calls" {...@@ -1591,11 +1591,11 @@ test "nosuspend resume async function calls" {
1591 };1591 };
1592 const S1 = struct {1592 const S1 = struct {
1593 fn c() S0 {1593 fn c() S0 {
1594 suspend;1594 suspend {}
1595 return S0{};1595 return S0{};
1596 }1596 }
1597 fn d() !S0 {1597 fn d() !S0 {
1598 suspend;1598 suspend {}
1599 return S0{};1599 return S0{};
1600 }1600 }
1601 };1601 };
test/stage1/behavior/math.zig+31-4
...@@ -229,16 +229,26 @@ fn testSignedWrappingEval(x: i32) void {...@@ -229,16 +229,26 @@ fn testSignedWrappingEval(x: i32) void {
229 expect(max_val == maxInt(i32));229 expect(max_val == maxInt(i32));
230}230}
231231
232test "negation wrapping" {232test "signed negation wrapping" {
233 testNegationWrappingEval(minInt(i16));233 testSignedNegationWrappingEval(minInt(i16));
234 comptime testNegationWrappingEval(minInt(i16));234 comptime testSignedNegationWrappingEval(minInt(i16));
235}235}
236fn testNegationWrappingEval(x: i16) void {236fn testSignedNegationWrappingEval(x: i16) void {
237 expect(x == -32768);237 expect(x == -32768);
238 const neg = -%x;238 const neg = -%x;
239 expect(neg == -32768);239 expect(neg == -32768);
240}240}
241241
242test "unsigned negation wrapping" {
243 testUnsignedNegationWrappingEval(1);
244 comptime testUnsignedNegationWrappingEval(1);
245}
246fn testUnsignedNegationWrappingEval(x: u16) void {
247 expect(x == 1);
248 const neg = -%x;
249 expect(neg == maxInt(u16));
250}
251
242test "unsigned 64-bit division" {252test "unsigned 64-bit division" {
243 test_u64_div();253 test_u64_div();
244 comptime test_u64_div();254 comptime test_u64_div();
...@@ -843,3 +853,20 @@ test "compare undefined literal with comptime_int" {...@@ -843,3 +853,20 @@ test "compare undefined literal with comptime_int" {
843 x = true;853 x = true;
844 expect(x);854 expect(x);
845}855}
856
857test "signed zeros are represented properly" {
858 const S = struct {
859 fn doTheTest() void {
860 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
861 const ST = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
862 var as_fp_val = -@as(T, 0.0);
863 var as_uint_val = @bitCast(ST, as_fp_val);
864 // Ensure the sign bit is set.
865 expect(as_uint_val >> (@typeInfo(T).Float.bits - 1) == 1);
866 }
867 }
868 };
869
870 S.doTheTest();
871 comptime S.doTheTest();
872}
test/tests.zig+16
...@@ -212,6 +212,22 @@ const test_targets = blk: {...@@ -212,6 +212,22 @@ const test_targets = blk: {
212 // .link_libc = true,212 // .link_libc = true,
213 //},213 //},
214214
215 TestTarget{
216 .target = .{
217 .cpu_arch = .powerpc,
218 .os_tag = .linux,
219 .abi = .none,
220 },
221 },
222 TestTarget{
223 .target = .{
224 .cpu_arch = .powerpc,
225 .os_tag = .linux,
226 .abi = .musl,
227 },
228 .link_libc = true,
229 },
230
215 TestTarget{231 TestTarget{
216 .target = .{232 .target = .{
217 .cpu_arch = .riscv64,233 .cpu_arch = .riscv64,
test/translate_c.zig+20-4
...@@ -3,6 +3,22 @@ const std = @import("std");...@@ -3,6 +3,22 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub fn addCases(cases: *tests.TranslateCContext) void {
6 cases.add("field access is grouped if necessary",
7 \\unsigned long foo(unsigned long x) {
8 \\ return ((union{unsigned long _x}){x})._x;
9 \\}
10 , &[_][]const u8{
11 \\pub export fn foo(arg_x: c_ulong) c_ulong {
12 \\ var x = arg_x;
13 \\ const union_unnamed_1 = extern union {
14 \\ _x: c_ulong,
15 \\ };
16 \\ return (union_unnamed_1{
17 \\ ._x = x,
18 \\ })._x;
19 \\}
20 });
21
6 cases.add("unnamed child types of typedef receive typedef's name",22 cases.add("unnamed child types of typedef receive typedef's name",
7 \\typedef enum {23 \\typedef enum {
8 \\ FooA,24 \\ FooA,
...@@ -111,7 +127,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -111,7 +127,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
111 \\ const A = @enumToInt(enum_Foo.A);127 \\ const A = @enumToInt(enum_Foo.A);
112 \\ const B = @enumToInt(enum_Foo.B);128 \\ const B = @enumToInt(enum_Foo.B);
113 \\ const C = @enumToInt(enum_Foo.C);129 \\ const C = @enumToInt(enum_Foo.C);
114 \\ var a: enum_Foo = @intToEnum(enum_Foo, B);130 \\ var a: enum_Foo = @import("std").meta.cast(enum_Foo, B);
115 \\ {131 \\ {
116 \\ const enum_Foo = extern enum(c_int) {132 \\ const enum_Foo = extern enum(c_int) {
117 \\ A,133 \\ A,
...@@ -122,7 +138,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -122,7 +138,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
122 \\ const A_2 = @enumToInt(enum_Foo.A);138 \\ const A_2 = @enumToInt(enum_Foo.A);
123 \\ const B_3 = @enumToInt(enum_Foo.B);139 \\ const B_3 = @enumToInt(enum_Foo.B);
124 \\ const C_4 = @enumToInt(enum_Foo.C);140 \\ const C_4 = @enumToInt(enum_Foo.C);
125 \\ var a_5: enum_Foo = @intToEnum(enum_Foo, B_3);141 \\ var a_5: enum_Foo = @import("std").meta.cast(enum_Foo, B_3);
126 \\ }142 \\ }
127 \\}143 \\}
128 });144 });
...@@ -1676,7 +1692,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1676,7 +1692,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1676 \\pub const e = @enumToInt(enum_unnamed_1.e);1692 \\pub const e = @enumToInt(enum_unnamed_1.e);
1677 \\pub const f = @enumToInt(enum_unnamed_1.f);1693 \\pub const f = @enumToInt(enum_unnamed_1.f);
1678 \\pub const g = @enumToInt(enum_unnamed_1.g);1694 \\pub const g = @enumToInt(enum_unnamed_1.g);
1679 \\pub export var h: enum_unnamed_1 = @intToEnum(enum_unnamed_1, e);1695 \\pub export var h: enum_unnamed_1 = @import("std").meta.cast(enum_unnamed_1, e);
1680 \\const enum_unnamed_2 = extern enum(c_int) {1696 \\const enum_unnamed_2 = extern enum(c_int) {
1681 \\ i,1697 \\ i,
1682 \\ j,1698 \\ j,
...@@ -2308,7 +2324,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2308,7 +2324,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2308 \\ var a = arg_a;2324 \\ var a = arg_a;
2309 \\ var b = arg_b;2325 \\ var b = arg_b;
2310 \\ var c = arg_c;2326 \\ var c = arg_c;
2311 \\ var d: enum_Foo = @intToEnum(enum_Foo, FooA);2327 \\ var d: enum_Foo = @import("std").meta.cast(enum_Foo, FooA);
2312 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));2328 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));
2313 \\ var f: c_int = @boolToInt((b != 0) and (c != null));2329 \\ var f: c_int = @boolToInt((b != 0) and (c != null));
2314 \\ var g: c_int = @boolToInt((a != 0) and (c != null));2330 \\ var g: c_int = @boolToInt((a != 0) and (c != null));
tools/update_cpu_features.zig+6
...@@ -663,6 +663,12 @@ const llvm_targets = [_]LlvmTarget{...@@ -663,6 +663,12 @@ const llvm_targets = [_]LlvmTarget{
663 .zig_name = "powerpc",663 .zig_name = "powerpc",
664 .llvm_name = "PowerPC",664 .llvm_name = "PowerPC",
665 .td_name = "PPC.td",665 .td_name = "PPC.td",
666 .feature_overrides = &.{
667 .{
668 .llvm_name = "ppc32",
669 .omit = true,
670 },
671 },
666 },672 },
667 .{673 .{
668 .zig_name = "riscv",674 .zig_name = "riscv",