authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-27 15:51:03-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-27 15:51:03-04:00
logb52057f05218d13901fe576bf2d472b657e58e6f
tree80203b7f809f94c3a1a49f6e9404331d8947f78b
parentd01609af2aaf5a3c9ddd2ddf75a5d211e0e94b07
parent47396c903cb118df9e5562f383026b0f460d38f6

Merge pull request 'compiler_rt: change `f80` abi so it can become compatible with cbe' (#35932) from jacobly/s390x-abi into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35932

320 files changed, 19181 insertions(+), 13424 deletions(-)

CMakeLists.txt+2
......@@ -358,6 +358,8 @@ set(ZIG_STAGE2_SOURCES
358358 src/codegen/c/type/render_defs.zig
359359 src/codegen/llvm.zig
360360 src/codegen/llvm/bindings.zig
361 src/codegen/loongarch/abi.zig
362 src/codegen/s390x/abi.zig
361363 src/crash_report.zig
362364 src/dev.zig
363365 src/libs/freebsd.zig
lib/compiler/aro/aro/Target.zig+3-3
......@@ -1559,15 +1559,15 @@ pub fn ptrBitWidth(target: *const Target) u16 {
15591559}
15601560
15611561pub fn cCharSignedness(target: *const Target) std.builtin.Signedness {
1562 return target.toZigTarget().cCharSignedness();
1562 return target.toZigTarget().cCharSignedness().?;
15631563}
15641564
15651565pub fn cTypeBitSize(target: *const Target, c_type: std.Target.CType) u16 {
1566 return target.toZigTarget().cTypeBitSize(c_type);
1566 return target.toZigTarget().cTypeBitSize(c_type).?;
15671567}
15681568
15691569pub fn cTypeAlignment(target: *const Target, c_type: std.Target.CType) u16 {
1570 return target.toZigTarget().cTypeAlignment(c_type);
1570 return target.toZigTarget().cTypeAlignment(c_type).?;
15711571}
15721572
15731573pub fn standardDynamicLinkerPath(target: *const Target) std.Target.DynamicLinker {
lib/compiler/reduce.zig+1-1
......@@ -400,7 +400,7 @@ fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast {
400400 file_path,
401401 gpa,
402402 .limited(std.math.maxInt(u32)),
403 .fromByteUnits(1),
403 .@"1",
404404 0,
405405 ) catch |err| {
406406 fatal("unable to open '{s}': {s}", .{ file_path, @errorName(err) });
lib/compiler/resinator/parse.zig+1-1
......@@ -1277,7 +1277,7 @@ pub const Parser = struct {
12771277 },
12781278 else => unreachable,
12791279 }
1280 @compileError("unreachable");
1280 comptime unreachable;
12811281 }
12821282
12831283 pub const OptionalParamParser = struct {
lib/compiler/test_runner.zig+11-11
......@@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void {
9191 return std.process.exit(0);
9292 },
9393 .query_test_metadata => {
94 testing.allocator_instance = .init(std.heap.page_allocator, .{});
95 defer if (testing.allocator_instance.deinit() != 0) {
96 @panic("internal test runner memory leak");
97 };
94 var sa: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{});
95 defer if (sa.deinit() != 0) @panic("internal test runner memory leak");
96 const gpa = sa.allocator();
9897
9998 var string_bytes: std.ArrayList(u8) = .empty;
100 defer string_bytes.deinit(testing.allocator);
101 try string_bytes.append(testing.allocator, 0); // Reserve 0 for null.
99 defer string_bytes.deinit(gpa);
100 try string_bytes.append(gpa, 0); // Reserve 0 for null.
102101
103102 const test_fns = builtin.test_functions;
104 const names = try testing.allocator.alloc(u32, test_fns.len);
105 defer testing.allocator.free(names);
106 const expected_panic_msgs = try testing.allocator.alloc(u32, test_fns.len);
107 defer testing.allocator.free(expected_panic_msgs);
103 const names = try gpa.alloc(u32, test_fns.len);
104 defer gpa.free(names);
105 const expected_panic_msgs = try gpa.alloc(u32, test_fns.len);
106 defer gpa.free(expected_panic_msgs);
108107
109108 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {
110109 name.* = @intCast(string_bytes.items.len);
111 try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1);
110 try string_bytes.ensureUnusedCapacity(gpa, test_fn.name.len + 1);
112111 string_bytes.appendSliceAssumeCapacity(test_fn.name);
113112 string_bytes.appendAssumeCapacity(0);
114113 expected_panic_msg.* = 0;
......@@ -377,6 +376,7 @@ pub fn mainSimple() anyerror!void {
377376 else => false,
378377 };
379378
379 testing.allocator_instance = .init(std.heap.page_allocator, .{});
380380 testing.io_instance = .init(testing.allocator, .{});
381381
382382 var passed: u64 = 0;
lib/compiler_rt.zig+120-168
......@@ -1,4 +1,5 @@
11const builtin = @import("builtin");
2const compiler_rt = @This();
23const ofmt_c = builtin.object_format == .c;
34const native_endian = builtin.cpu.arch.endian();
45
......@@ -84,144 +85,17 @@ comptime {
8485 // Float routines
8586 // conversion
8687 _ = @import("compiler_rt/extendf.zig");
87 _ = @import("compiler_rt/extendhfsf2.zig");
88 _ = @import("compiler_rt/extendhfdf2.zig");
89 _ = @import("compiler_rt/extendhftf2.zig");
90 _ = @import("compiler_rt/extendhfxf2.zig");
91 _ = @import("compiler_rt/extendsfdf2.zig");
92 _ = @import("compiler_rt/extendsftf2.zig");
93 _ = @import("compiler_rt/extendsfxf2.zig");
94 _ = @import("compiler_rt/extenddftf2.zig");
95 _ = @import("compiler_rt/extenddfxf2.zig");
96 _ = @import("compiler_rt/extendxftf2.zig");
97
9888 _ = @import("compiler_rt/truncf.zig");
99 _ = @import("compiler_rt/truncsfhf2.zig");
100 _ = @import("compiler_rt/truncdfhf2.zig");
101 _ = @import("compiler_rt/truncdfsf2.zig");
102 _ = @import("compiler_rt/truncxfhf2.zig");
103 _ = @import("compiler_rt/truncxfsf2.zig");
104 _ = @import("compiler_rt/truncxfdf2.zig");
105 _ = @import("compiler_rt/trunctfhf2.zig");
106 _ = @import("compiler_rt/trunctfsf2.zig");
107 _ = @import("compiler_rt/trunctfdf2.zig");
108 _ = @import("compiler_rt/trunctfxf2.zig");
109
11089 _ = @import("compiler_rt/int_from_float.zig");
111 _ = @import("compiler_rt/fixhfei.zig");
112 _ = @import("compiler_rt/fixsfsi.zig");
113 _ = @import("compiler_rt/fixsfdi.zig");
114 _ = @import("compiler_rt/fixsfti.zig");
115 _ = @import("compiler_rt/fixsfei.zig");
116 _ = @import("compiler_rt/fixdfsi.zig");
117 _ = @import("compiler_rt/fixdfdi.zig");
118 _ = @import("compiler_rt/fixdfti.zig");
119 _ = @import("compiler_rt/fixdfei.zig");
120 _ = @import("compiler_rt/fixtfsi.zig");
121 _ = @import("compiler_rt/fixtfdi.zig");
122 _ = @import("compiler_rt/fixtfti.zig");
123 _ = @import("compiler_rt/fixtfei.zig");
124 _ = @import("compiler_rt/fixxfsi.zig");
125 _ = @import("compiler_rt/fixxfdi.zig");
126 _ = @import("compiler_rt/fixxfei.zig");
127
128 _ = @import("compiler_rt/fixunshfsi.zig");
129 _ = @import("compiler_rt/fixunshfdi.zig");
130 _ = @import("compiler_rt/fixunshfti.zig");
131 _ = @import("compiler_rt/fixunshfei.zig");
132 _ = @import("compiler_rt/fixunssfsi.zig");
133 _ = @import("compiler_rt/fixunssfdi.zig");
134 _ = @import("compiler_rt/fixunssfti.zig");
135 _ = @import("compiler_rt/fixunssfei.zig");
136 _ = @import("compiler_rt/fixunsdfsi.zig");
137 _ = @import("compiler_rt/fixunsdfdi.zig");
138 _ = @import("compiler_rt/fixunsdfti.zig");
139 _ = @import("compiler_rt/fixunsdfei.zig");
140 _ = @import("compiler_rt/fixunstfsi.zig");
141 _ = @import("compiler_rt/fixunstfdi.zig");
142 _ = @import("compiler_rt/fixunstfti.zig");
143 _ = @import("compiler_rt/fixunstfei.zig");
144 _ = @import("compiler_rt/fixunsxfsi.zig");
145 _ = @import("compiler_rt/fixunsxfdi.zig");
146 _ = @import("compiler_rt/fixunsxfti.zig");
147 _ = @import("compiler_rt/fixunsxfei.zig");
148
14990 _ = @import("compiler_rt/float_from_int.zig");
150 _ = @import("compiler_rt/floatsihf.zig");
151 _ = @import("compiler_rt/floatsisf.zig");
152 _ = @import("compiler_rt/floatsidf.zig");
153 _ = @import("compiler_rt/floatsitf.zig");
154 _ = @import("compiler_rt/floatsixf.zig");
155 _ = @import("compiler_rt/floatdihf.zig");
156 _ = @import("compiler_rt/floatdisf.zig");
157 _ = @import("compiler_rt/floatdidf.zig");
158 _ = @import("compiler_rt/floatditf.zig");
159 _ = @import("compiler_rt/floatdixf.zig");
160 _ = @import("compiler_rt/floattihf.zig");
161 _ = @import("compiler_rt/floattisf.zig");
162 _ = @import("compiler_rt/floattidf.zig");
163 _ = @import("compiler_rt/floattitf.zig");
164 _ = @import("compiler_rt/floattixf.zig");
165 _ = @import("compiler_rt/floateihf.zig");
166 _ = @import("compiler_rt/floateisf.zig");
167 _ = @import("compiler_rt/floateidf.zig");
168 _ = @import("compiler_rt/floateitf.zig");
169 _ = @import("compiler_rt/floateixf.zig");
170 _ = @import("compiler_rt/floatunsihf.zig");
171 _ = @import("compiler_rt/floatunsisf.zig");
172 _ = @import("compiler_rt/floatunsidf.zig");
173 _ = @import("compiler_rt/floatunsitf.zig");
174 _ = @import("compiler_rt/floatunsixf.zig");
175 _ = @import("compiler_rt/floatundihf.zig");
176 _ = @import("compiler_rt/floatundisf.zig");
177 _ = @import("compiler_rt/floatundidf.zig");
178 _ = @import("compiler_rt/floatunditf.zig");
179 _ = @import("compiler_rt/floatundixf.zig");
180 _ = @import("compiler_rt/floatuntihf.zig");
181 _ = @import("compiler_rt/floatuntisf.zig");
182 _ = @import("compiler_rt/floatuntidf.zig");
183 _ = @import("compiler_rt/floatuntitf.zig");
184 _ = @import("compiler_rt/floatuntixf.zig");
185 _ = @import("compiler_rt/floatuneihf.zig");
186 _ = @import("compiler_rt/floatuneisf.zig");
187 _ = @import("compiler_rt/floatuneidf.zig");
188 _ = @import("compiler_rt/floatuneitf.zig");
189 _ = @import("compiler_rt/floatuneixf.zig");
19091
19192 // comparison
19293 _ = @import("compiler_rt/comparef.zig");
193 _ = @import("compiler_rt/cmpdf2.zig");
194 _ = @import("compiler_rt/cmptf2.zig");
195 _ = @import("compiler_rt/cmpxf2.zig");
196 _ = @import("compiler_rt/unorddf2.zig");
197 _ = @import("compiler_rt/gehf2.zig");
198 _ = @import("compiler_rt/gesf2.zig");
199 _ = @import("compiler_rt/gedf2.zig");
200 _ = @import("compiler_rt/gexf2.zig");
201 _ = @import("compiler_rt/getf2.zig");
20294
20395 // arithmetic
20496 _ = @import("compiler_rt/addf3.zig");
205 _ = @import("compiler_rt/addhf3.zig");
206 _ = @import("compiler_rt/addsf3.zig");
207 _ = @import("compiler_rt/adddf3.zig");
208 _ = @import("compiler_rt/addtf3.zig");
209 _ = @import("compiler_rt/addxf3.zig");
210
211 _ = @import("compiler_rt/subhf3.zig");
212 _ = @import("compiler_rt/subsf3.zig");
213 _ = @import("compiler_rt/subdf3.zig");
214 _ = @import("compiler_rt/subtf3.zig");
215 _ = @import("compiler_rt/subxf3.zig");
216
21797 _ = @import("compiler_rt/mulf3.zig");
218 _ = @import("compiler_rt/mulhf3.zig");
219 _ = @import("compiler_rt/mulsf3.zig");
220 _ = @import("compiler_rt/muldf3.zig");
221 _ = @import("compiler_rt/multf3.zig");
222 _ = @import("compiler_rt/mulxf3.zig");
22398
224 _ = @import("compiler_rt/divhf3.zig");
22599 _ = @import("compiler_rt/divsf3.zig");
226100 _ = @import("compiler_rt/divdf3.zig");
227101 _ = @import("compiler_rt/divxf3.zig");
......@@ -235,25 +109,17 @@ comptime {
235109 symbol(&__negsf2, "__negsf2");
236110 symbol(&__negdf2, "__negdf2");
237111 }
238 if (want_ppc_abi) symbol(&__negtf2, "__negkf2");
239 symbol(&__negtf2, "__negtf2");
112 if (want_ppc_abi) {
113 symbol(&__negtf2, "__negkf2");
114 } else {
115 symbol(&__negtf2, "__negtf2");
116 }
240117 symbol(&__negxf2, "__negxf2");
241118
242119 // other
243120 _ = @import("compiler_rt/powiXf2.zig");
244121 _ = @import("compiler_rt/mulc3.zig");
245 _ = @import("compiler_rt/mulhc3.zig");
246 _ = @import("compiler_rt/mulsc3.zig");
247 _ = @import("compiler_rt/muldc3.zig");
248 _ = @import("compiler_rt/mulxc3.zig");
249 _ = @import("compiler_rt/multc3.zig");
250
251122 _ = @import("compiler_rt/divc3.zig");
252 _ = @import("compiler_rt/divhc3.zig");
253 _ = @import("compiler_rt/divsc3.zig");
254 _ = @import("compiler_rt/divdc3.zig");
255 _ = @import("compiler_rt/divxc3.zig");
256 _ = @import("compiler_rt/divtc3.zig");
257123
258124 // Math routines. Alphabetically sorted.
259125 _ = @import("compiler_rt/cos.zig");
......@@ -279,7 +145,7 @@ comptime {
279145 _ = @import("compiler_rt/divmodei4.zig");
280146 _ = @import("compiler_rt/udivmodei4.zig");
281147
282 _ = @import("compiler_rt/limb64.zig");
148 if (builtin.cpu.arch.isWasm()) _ = @import("compiler_rt/limb64.zig");
283149
284150 // extra
285151 _ = @import("compiler_rt/os_version_check.zig");
......@@ -290,7 +156,7 @@ comptime {
290156 _ = @import("compiler_rt/clear_cache.zig");
291157 _ = @import("compiler_rt/hexagon.zig");
292158
293 if (@import("builtin").object_format != .c) {
159 if (builtin.object_format != .c) {
294160 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig");
295161 _ = @import("compiler_rt/stack_probe.zig");
296162
......@@ -366,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) {
366232 .gnueabihf,
367233 .android,
368234 .androideabi,
369 => switch (builtin.cpu.arch) {
370 .arm, .armeb, .thumb, .thumbeb => true,
371 else => false,
372 },
235 => builtin.cpu.arch.isArm(),
373236 else => false,
374237};
375238
......@@ -443,19 +306,108 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {
443306pub const want_sparc64_abi = builtin.cpu.arch == .sparc64;
444307pub const want_sparc32_abi = builtin.cpu.arch == .sparc;
445308
446pub fn F16T(comptime OtherType: type) type {
447 return switch (builtin.cpu.arch) {
448 .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) {
449 // Starting with LLVM 16, Darwin uses different abi for f16
450 // depending on the type of the other return/argument..???
451 f32, f64 => u16,
452 f80, f128 => f16,
453 else => unreachable,
454 } else f16,
455 else => f16,
309/// For operations converting between `f16` and another floating point type.
310pub fn f16Conv(comptime OtherType: type) type {
311 switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) {
312 .hard => {},
313 .soft => return softFloatAbi(f16),
314 }
315 if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) {
316 else => unreachable,
317 // Starting with LLVM 16, Darwin uses different abi for f16
318 // depending on the type of the other return/argument..???
319 f32, f64 => return softFloatAbi(f16),
320 f80, f128 => {},
321 };
322 return hardFloatAbi(f16);
323}
324pub const @"f16" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) {
325 .hard => hardFloatAbi(f16),
326 .soft => softFloatAbi(f16),
327};
328pub const @"f32" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 32)) {
329 .hard => hardFloatAbi(f32),
330 .soft => softFloatAbi(f32),
331};
332pub const @"f64" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 64)) {
333 .hard => hardFloatAbi(f64),
334 .soft => softFloatAbi(f64),
335};
336pub const @"f80" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 80)) {
337 .hard => hardFloatAbi(f80),
338 .soft => struct {
339 pub const Abi = extern struct { mantissa: u64, exponent: u16 };
340 const Repr = packed struct { mantissa: u64, exponent: u16 };
341 pub inline fn toAbi(raw: f80) Abi {
342 const repr: Repr = @bitCast(raw);
343 return .{ .mantissa = repr.mantissa, .exponent = repr.exponent };
344 }
345 pub inline fn fromAbi(abi: Abi) f80 {
346 const repr: Repr = .{ .mantissa = abi.mantissa, .exponent = abi.exponent };
347 return @bitCast(repr);
348 }
349 pub const complex = complexAbi(f80, @This());
350 },
351};
352pub const @"f128" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 128)) {
353 .hard => hardFloatAbi(f128),
354 .soft => struct {
355 pub const Abi = switch (builtin.cpu.arch.endian()) {
356 .big => extern struct { hi: u64, lo: u64 },
357 .little => extern struct { lo: u64, hi: u64 },
358 };
359 const Repr = packed struct { lo: u64, hi: u64 };
360 pub inline fn toAbi(raw: f128) Abi {
361 const repr: Repr = @bitCast(raw);
362 return .{ .lo = repr.lo, .hi = repr.hi };
363 }
364 pub inline fn fromAbi(abi: Abi) f128 {
365 const repr: Repr = .{ .lo = abi.lo, .hi = abi.hi };
366 return @bitCast(repr);
367 }
368 pub const complex = complexAbi(f128, @This());
369 },
370};
371fn hardFloatAbi(comptime Float: type) type {
372 return struct {
373 pub const Abi = Float;
374 pub inline fn toAbi(raw: Float) Abi {
375 return raw;
376 }
377 pub inline fn fromAbi(abi: Abi) Float {
378 return abi;
379 }
380 pub const complex = complexAbi(Float, @This());
381 };
382}
383fn softFloatAbi(comptime Float: type) type {
384 return struct {
385 pub const Abi = @Int(.unsigned, @bitSizeOf(Float));
386 pub inline fn toAbi(raw: Float) Abi {
387 return @bitCast(raw);
388 }
389 pub inline fn fromAbi(abi: Abi) Float {
390 return @bitCast(abi);
391 }
392 pub const complex = complexAbi(Float, @This());
393 };
394}
395fn complexAbi(comptime Float: type, comptime float: type) type {
396 return struct {
397 pub const Abi = extern struct { real: float.Abi, imag: float.Abi };
398 pub inline fn toAbi(raw: Complex(Float)) Abi {
399 return .{ .real = float.toAbi(raw.real), .imag = float.toAbi(raw.imag) };
400 }
401 pub inline fn fromAbi(abi: Abi) Complex(Float) {
402 return .{ .real = float.fromAbi(abi.real), .imag = float.fromAbi(abi.imag) };
403 }
456404 };
457405}
458406
407pub fn Complex(comptime Float: type) type {
408 return struct { real: Float, imag: Float };
409}
410
459411pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
460412 switch (Z) {
461413 u16 => {
......@@ -588,31 +540,31 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {
588540 return @bitCast(negated);
589541}
590542
591fn __negxf2(a: f80) callconv(.c) f80 {
592 return fneg(a);
543fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
544 return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a)));
593545}
594546
595fn __neghf2(a: f16) callconv(.c) f16 {
596 return fneg(a);
547fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
548 return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a)));
597549}
598550
599fn __negdf2(a: f64) callconv(.c) f64 {
600 return fneg(a);
551fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
552 return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a)));
601553}
602554
603fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
604 return fneg(a);
555fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
556 return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a)));
605557}
606558
607fn __negtf2(a: f128) callconv(.c) f128 {
608 return fneg(a);
559fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
560 return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a)));
609561}
610562
611fn __negsf2(a: f32) callconv(.c) f32 {
563fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
612564 return fneg(a);
613565}
614566
615fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
567fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
616568 return fneg(a);
617569}
618570
lib/compiler_rt/absv.zig+1-2
......@@ -14,8 +14,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST {
1414 const sign: ST = a >> N - 1;
1515 x +%= sign;
1616 x ^= sign;
17 if (x < 0)
18 @panic("compiler_rt absv: overflow");
17 if (x < 0) @panic("integer overflow");
1918 return x;
2019}
2120
lib/compiler_rt/absvdi2.zig+3-2
......@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const absv = @import("./absv.zig").absv;
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const absv = @import("absv.zig").absv;
34
45comptime {
56 symbol(&__absvdi2, "__absvdi2");
lib/compiler_rt/absvsi2.zig+1-1
......@@ -1,6 +1,6 @@
11const compiler_rt = @import("../compiler_rt.zig");
22const symbol = compiler_rt.symbol;
3const absv = @import("./absv.zig").absv;
3const absv = @import("absv.zig").absv;
44
55comptime {
66 symbol(&__absvsi2, "__absvsi2");
lib/compiler_rt/absvti2.zig+3-2
......@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const absv = @import("./absv.zig").absv;
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const absv = @import("absv.zig").absv;
34
45comptime {
56 symbol(&__absvti2, "__absvti2");
lib/compiler_rt/adddf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const addf3 = @import("./addf3.zig").addf3;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dadd, "__aeabi_dadd");
8 } else {
9 symbol(&__adddf3, "__adddf3");
10 }
11}
12
13fn __adddf3(a: f64, b: f64) callconv(.c) f64 {
14 return addf3(f64, a, b);
15}
16
17fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return addf3(f64, a, b);
19}
lib/compiler_rt/addf3.zig+132-1
......@@ -1,12 +1,143 @@
11const std = @import("std");
22const math = std.math;
33const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45const normalize = compiler_rt.normalize;
56
7comptime {
8 symbol(&__addhf3, "__addhf3");
9 if (compiler_rt.want_aeabi) {
10 symbol(&__aeabi_fadd, "__aeabi_fadd");
11 symbol(&__aeabi_dadd, "__aeabi_dadd");
12 } else {
13 symbol(&__addsf3, "__addsf3");
14 symbol(&__adddf3, "__adddf3");
15 }
16 symbol(&__addxf3, "__addxf3");
17 if (compiler_rt.want_ppc_abi) {
18 symbol(&__addtf3, "__addkf3");
19 } else if (compiler_rt.want_sparc64_abi) {
20 symbol(&_Qp_add, "_Qp_add");
21 } else if (compiler_rt.want_sparc32_abi) {
22 symbol(&__addtf3, "_Q_add");
23 } else {
24 symbol(&__addtf3, "__addtf3");
25 }
26}
27
28fn __addhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
29 return compiler_rt.f16.toAbi(add_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
30}
31pub fn add_f16(a: f16, b: f16) f16 {
32 return addf3(f16, a, b);
33}
34
35fn __addsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
36 return compiler_rt.f32.toAbi(add_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
37}
38fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
39 return add_f32(a, b);
40}
41pub fn add_f32(a: f32, b: f32) f32 {
42 return addf3(f32, a, b);
43}
44
45fn __adddf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
46 return compiler_rt.f64.toAbi(add_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
47}
48fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
49 return add_f64(a, b);
50}
51pub fn add_f64(a: f64, b: f64) f64 {
52 return addf3(f64, a, b);
53}
54
55fn __addxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
56 return compiler_rt.f80.toAbi(add_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
57}
58pub fn add_f80(a: f80, b: f80) f80 {
59 return addf3(f80, a, b);
60}
61
62fn __addtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
63 return compiler_rt.f128.toAbi(add_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
64}
65fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void {
66 c.* = add_f128(a.*, b.*);
67}
68pub fn add_f128(a: f128, b: f128) f128 {
69 return addf3(f128, a, b);
70}
71
72comptime {
73 symbol(&__subhf3, "__subhf3");
74 if (compiler_rt.want_aeabi) {
75 symbol(&__aeabi_fsub, "__aeabi_fsub");
76 symbol(&__aeabi_dsub, "__aeabi_dsub");
77 } else {
78 symbol(&__subsf3, "__subsf3");
79 symbol(&__subdf3, "__subdf3");
80 }
81 symbol(&__subxf3, "__subxf3");
82 if (compiler_rt.want_ppc_abi) {
83 symbol(&__subtf3, "__subkf3");
84 } else if (compiler_rt.want_sparc64_abi) {
85 symbol(&_Qp_sub, "_Qp_sub");
86 } else if (compiler_rt.want_sparc32_abi) {
87 symbol(&__subtf3, "_Q_sub");
88 } else {
89 symbol(&__subtf3, "__subtf3");
90 }
91}
92
93fn __subhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
94 return compiler_rt.f16.toAbi(sub_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
95}
96pub fn sub_f16(a: f16, b: f16) f16 {
97 return add_f16(a, compiler_rt.fneg(b));
98}
99
100fn __subsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
101 return compiler_rt.f32.toAbi(sub_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
102}
103fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
104 return sub_f32(a, b);
105}
106pub fn sub_f32(a: f32, b: f32) f32 {
107 return add_f32(a, compiler_rt.fneg(b));
108}
109
110fn __subdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
111 return compiler_rt.f64.toAbi(sub_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
112}
113fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
114 return sub_f64(a, b);
115}
116pub fn sub_f64(a: f64, b: f64) f64 {
117 return add_f64(a, compiler_rt.fneg(b));
118}
119
120fn __subxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
121 return compiler_rt.f80.toAbi(sub_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
122}
123pub fn sub_f80(a: f80, b: f80) f80 {
124 return add_f80(a, compiler_rt.fneg(b));
125}
126
127fn __subtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
128 return compiler_rt.f128.toAbi(sub_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
129}
130fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
131 c.* = sub_f128(a.*, b.*);
132}
133pub fn sub_f128(a: f128, b: f128) f128 {
134 return add_f128(a, compiler_rt.fneg(b));
135}
136
6137/// Ported from:
7138///
8139/// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc
9pub inline fn addf3(comptime T: type, a: T, b: T) T {
140inline fn addf3(comptime T: type, a: T, b: T) T {
10141 const bits = @typeInfo(T).float.bits;
11142 const Z = @Int(.unsigned, bits);
12143
lib/compiler_rt/addf3_test.zig+7-6
......@@ -8,12 +8,13 @@ const builtin = @import("builtin");
88const math = std.math;
99const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);
1010
11const __addtf3 = @import("addtf3.zig").__addtf3;
12const __addxf3 = @import("addxf3.zig").__addxf3;
13const __subtf3 = @import("subtf3.zig").__subtf3;
11const impl = @import("addf3.zig");
12const add_f128 = impl.add_f128;
13const add_f80 = impl.add_f80;
14const sub_f128 = impl.sub_f128;
1415
1516fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
16 const x = __addtf3(a, b);
17 const x = add_f128(a, b);
1718
1819 const rep: u128 = @bitCast(x);
1920 const hi: u64 = @intCast(rep >> 64);
......@@ -52,7 +53,7 @@ test "addtf3" {
5253}
5354
5455fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
55 const x = __subtf3(a, b);
56 const x = sub_f128(a, b);
5657
5758 const rep: u128 = @bitCast(x);
5859 const hi: u64 = @intCast(rep >> 64);
......@@ -91,7 +92,7 @@ test "subtf3" {
9192const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));
9293
9394fn test__addxf3(a: f80, b: f80, expected: u80) !void {
94 const x = __addxf3(a, b);
95 const x = add_f80(a, b);
9596 const rep: u80 = @bitCast(x);
9697
9798 if (rep == expected)
lib/compiler_rt/addhf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 symbol(&__addhf3, "__addhf3");
7}
8
9fn __addhf3(a: f16, b: f16) callconv(.c) f16 {
10 return addf3(f16, a, b);
11}
lib/compiler_rt/addsf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const addf3 = @import("./addf3.zig").addf3;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_fadd, "__aeabi_fadd");
8 } else {
9 symbol(&__addsf3, "__addsf3");
10 }
11}
12
13fn __addsf3(a: f32, b: f32) callconv(.c) f32 {
14 return addf3(f32, a, b);
15}
16
17fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return addf3(f32, a, b);
19}
lib/compiler_rt/addtf3.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__addtf3, "__addkf3");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_add, "_Qp_add");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__addtf3, "_Q_add");
12 }
13 symbol(&__addtf3, "__addtf3");
14}
15
16pub fn __addtf3(a: f128, b: f128) callconv(.c) f128 {
17 return addf3(f128, a, b);
18}
19
20fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void {
21 c.* = addf3(f128, a.*, b.*);
22}
lib/compiler_rt/addvdi3.zig+3-2
......@@ -1,4 +1,5 @@
1const symbol = @import("../compiler_rt.zig").symbol;
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
23const testing = @import("std").testing;
34
45comptime {
......@@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {
910 const sum = a +% b;
1011 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
1112 // not match it. In other words, iff the sum sign is not the sign of either operand.
12 if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
13 if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow");
1314 return sum;
1415}
1516
lib/compiler_rt/addvsi3.zig+1-1
......@@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
1010 const sum = a +% b;
1111 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
1212 // not match it. In other words, iff the sum sign is not the sign of either operand.
13 if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
13 if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow");
1414 return sum;
1515}
1616
lib/compiler_rt/addxf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 symbol(&__addxf3, "__addxf3");
7}
8
9pub fn __addxf3(a: f80, b: f80) callconv(.c) f80 {
10 return addf3(f80, a, b);
11}
lib/compiler_rt/atomics.zig+1-1
......@@ -5,7 +5,7 @@ const arch = cpu.arch;
55const std = @import("std");
66
77const compiler_rt = @import("../compiler_rt.zig");
8const symbol = @import("../compiler_rt.zig").symbol;
8const symbol = compiler_rt.symbol;
99
1010// This parameter is true iff the target architecture supports the bare minimum
1111// to implement the atomic load/store intrinsics.
lib/compiler_rt/aulldiv.zig+1-1
......@@ -1,7 +1,7 @@
11const builtin = @import("builtin");
22
33const compiler_rt = @import("../compiler_rt.zig");
4const symbol = @import("../compiler_rt.zig").symbol;
4const symbol = compiler_rt.symbol;
55
66comptime {
77 if (compiler_rt.want_windows_x86_msvc_abi) {
lib/compiler_rt/cmpdf2.zig deleted-67
......@@ -1,67 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const comparef = @import("./comparef.zig");
5const symbol = @import("../compiler_rt.zig").symbol;
6
7comptime {
8 if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq");
10 symbol(&__aeabi_dcmplt, "__aeabi_dcmplt");
11 symbol(&__aeabi_dcmple, "__aeabi_dcmple");
12 } else {
13 symbol(&__eqdf2, "__eqdf2");
14 symbol(&__nedf2, "__nedf2");
15 symbol(&__ledf2, "__ledf2");
16 symbol(&__cmpdf2, "__cmpdf2");
17 symbol(&__ltdf2, "__ltdf2");
18 }
19}
20
21/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
22/// if a is greater than b, they return 1; and if a and b are equal they return 0.
23/// If either argument is NaN they return 1..."
24///
25/// Note that this matches the definition of `__ledf2`, `__eqdf2`, `__nedf2`, `__cmpdf2`,
26/// and `__ltdf2`.
27fn __cmpdf2(a: f64, b: f64) callconv(.c) i32 {
28 return @backingInt(comparef.cmpf2(f64, comparef.LE, a, b));
29}
30
31/// "These functions return a value less than or equal to zero if neither argument is NaN,
32/// and a is less than or equal to b."
33pub fn __ledf2(a: f64, b: f64) callconv(.c) i32 {
34 return __cmpdf2(a, b);
35}
36
37/// "These functions return zero if neither argument is NaN, and a and b are equal."
38/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined
39/// to have the same return value.
40pub fn __eqdf2(a: f64, b: f64) callconv(.c) i32 {
41 return __cmpdf2(a, b);
42}
43
44/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
45/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined
46/// to have the same return value.
47pub fn __nedf2(a: f64, b: f64) callconv(.c) i32 {
48 return __cmpdf2(a, b);
49}
50
51/// "These functions return a value less than zero if neither argument is NaN, and a
52/// is strictly less than b."
53pub fn __ltdf2(a: f64, b: f64) callconv(.c) i32 {
54 return __cmpdf2(a, b);
55}
56
57fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
58 return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal);
59}
60
61fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
62 return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Less);
63}
64
65fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
66 return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) != .Greater);
67}
lib/compiler_rt/cmptf2.zig deleted-146
......@@ -1,146 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const comparef = @import("./comparef.zig");
5const symbol = @import("../compiler_rt.zig").symbol;
6
7comptime {
8 if (compiler_rt.want_ppc_abi) {
9 symbol(&__eqtf2, "__eqkf2");
10 symbol(&__netf2, "__nekf2");
11 symbol(&__lttf2, "__ltkf2");
12 symbol(&__letf2, "__lekf2");
13 } else if (compiler_rt.want_sparc64_abi) {
14 symbol(&_Qp_cmp, "_Qp_cmp");
15 symbol(&_Qp_feq, "_Qp_feq");
16 symbol(&_Qp_fne, "_Qp_fne");
17 symbol(&_Qp_flt, "_Qp_flt");
18 symbol(&_Qp_fle, "_Qp_fle");
19 symbol(&_Qp_fgt, "_Qp_fgt");
20 symbol(&_Qp_fge, "_Qp_fge");
21 } else if (compiler_rt.want_sparc32_abi) {
22 symbol(&_Q_cmp, "_Q_cmp");
23 symbol(&_Q_feq, "_Q_feq");
24 symbol(&_Q_fne, "_Q_fne");
25 symbol(&_Q_flt, "_Q_flt");
26 symbol(&_Q_fle, "_Q_fle");
27 symbol(&_Q_fgt, "_Q_fgt");
28 symbol(&_Q_fge, "_Q_fge");
29 }
30 symbol(&__eqtf2, "__eqtf2");
31 symbol(&__netf2, "__netf2");
32 symbol(&__letf2, "__letf2");
33 symbol(&__cmptf2, "__cmptf2");
34 symbol(&__lttf2, "__lttf2");
35}
36
37/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
38/// if a is greater than b, they return 1; and if a and b are equal they return 0.
39/// If either argument is NaN they return 1..."
40///
41/// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`,
42/// and `__lttf2`.
43fn __cmptf2(a: f128, b: f128) callconv(.c) i32 {
44 return @backingInt(comparef.cmpf2(f128, comparef.LE, a, b));
45}
46
47/// "These functions return a value less than or equal to zero if neither argument is NaN,
48/// and a is less than or equal to b."
49fn __letf2(a: f128, b: f128) callconv(.c) i32 {
50 return __cmptf2(a, b);
51}
52
53/// "These functions return zero if neither argument is NaN, and a and b are equal."
54/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
55/// to have the same return value.
56fn __eqtf2(a: f128, b: f128) callconv(.c) i32 {
57 return __cmptf2(a, b);
58}
59
60/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
61/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
62/// to have the same return value.
63fn __netf2(a: f128, b: f128) callconv(.c) i32 {
64 return __cmptf2(a, b);
65}
66
67/// "These functions return a value less than zero if neither argument is NaN, and a
68/// is strictly less than b."
69fn __lttf2(a: f128, b: f128) callconv(.c) i32 {
70 return __cmptf2(a, b);
71}
72
73const SparcFCMP = enum(i32) {
74 Equal = 0,
75 Less = 1,
76 Greater = 2,
77 Unordered = 3,
78};
79
80fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) i32 {
81 return @backingInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*));
82}
83
84fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) bool {
85 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Equal;
86}
87
88fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) bool {
89 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) != .Equal;
90}
91
92fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) bool {
93 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Less;
94}
95
96fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) bool {
97 return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Greater;
98}
99
100fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) bool {
101 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) {
102 .Equal, .Greater => true,
103 .Less, .Unordered => false,
104 };
105}
106
107fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) bool {
108 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) {
109 .Equal, .Less => true,
110 .Greater, .Unordered => false,
111 };
112}
113
114fn _Q_cmp(a: f128, b: f128) callconv(.c) i32 {
115 return @backingInt(comparef.cmpf2(f128, SparcFCMP, a, b));
116}
117
118fn _Q_feq(a: f128, b: f128) callconv(.c) bool {
119 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Equal;
120}
121
122fn _Q_fne(a: f128, b: f128) callconv(.c) bool {
123 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) != .Equal;
124}
125
126fn _Q_flt(a: f128, b: f128) callconv(.c) bool {
127 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Less;
128}
129
130fn _Q_fgt(a: f128, b: f128) callconv(.c) bool {
131 return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Greater;
132}
133
134fn _Q_fge(a: f128, b: f128) callconv(.c) bool {
135 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) {
136 .Equal, .Greater => true,
137 .Less, .Unordered => false,
138 };
139}
140
141fn _Q_fle(a: f128, b: f128) callconv(.c) bool {
142 return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) {
143 .Equal, .Less => true,
144 .Greater, .Unordered => false,
145 };
146}
lib/compiler_rt/cmpxf2.zig deleted-49
......@@ -1,49 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const comparef = @import("./comparef.zig");
6
7comptime {
8 symbol(&__eqxf2, "__eqxf2");
9 symbol(&__nexf2, "__nexf2");
10 symbol(&__lexf2, "__lexf2");
11 symbol(&__cmpxf2, "__cmpxf2");
12 symbol(&__ltxf2, "__ltxf2");
13}
14
15/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
16/// if a is greater than b, they return 1; and if a and b are equal they return 0.
17/// If either argument is NaN they return 1..."
18///
19/// Note that this matches the definition of `__lexf2`, `__eqxf2`, `__nexf2`, `__cmpxf2`,
20/// and `__ltxf2`.
21fn __cmpxf2(a: f80, b: f80) callconv(.c) i32 {
22 return @backingInt(comparef.cmp_f80(comparef.LE, a, b));
23}
24
25/// "These functions return a value less than or equal to zero if neither argument is NaN,
26/// and a is less than or equal to b."
27fn __lexf2(a: f80, b: f80) callconv(.c) i32 {
28 return __cmpxf2(a, b);
29}
30
31/// "These functions return zero if neither argument is NaN, and a and b are equal."
32/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined
33/// to have the same return value.
34fn __eqxf2(a: f80, b: f80) callconv(.c) i32 {
35 return __cmpxf2(a, b);
36}
37
38/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
39/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined
40/// to have the same return value.
41fn __nexf2(a: f80, b: f80) callconv(.c) i32 {
42 return __cmpxf2(a, b);
43}
44
45/// "These functions return a value less than zero if neither argument is NaN, and a
46/// is strictly less than b."
47fn __ltxf2(a: f80, b: f80) callconv(.c) i32 {
48 return __cmpxf2(a, b);
49}
lib/compiler_rt/comparedf2_test.zig+17-73
......@@ -5,52 +5,12 @@
55const std = @import("std");
66const builtin = @import("builtin");
77
8const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;
9const __ledf2 = @import("./cmpdf2.zig").__ledf2;
10const __ltdf2 = @import("./cmpdf2.zig").__ltdf2;
11const __nedf2 = @import("./cmpdf2.zig").__nedf2;
8const compiler_rt = @import("../compiler_rt.zig");
129
13const __gedf2 = @import("./gedf2.zig").__gedf2;
14const __gtdf2 = @import("./gedf2.zig").__gtdf2;
15
16const __unorddf2 = @import("./unorddf2.zig").__unorddf2;
17
18const TestVector = struct {
19 a: f64,
20 b: f64,
21 eqReference: c_int,
22 geReference: c_int,
23 gtReference: c_int,
24 leReference: c_int,
25 ltReference: c_int,
26 neReference: c_int,
27 unReference: c_int,
28};
29
30fn test__cmpdf2(vector: TestVector) bool {
31 if (__eqdf2(vector.a, vector.b) != vector.eqReference) {
32 return false;
33 }
34 if (__gedf2(vector.a, vector.b) != vector.geReference) {
35 return false;
36 }
37 if (__gtdf2(vector.a, vector.b) != vector.gtReference) {
38 return false;
39 }
40 if (__ledf2(vector.a, vector.b) != vector.leReference) {
41 return false;
42 }
43 if (__ltdf2(vector.a, vector.b) != vector.ltReference) {
44 return false;
45 }
46 if (__nedf2(vector.a, vector.b) != vector.neReference) {
47 return false;
48 }
49 if (__unorddf2(vector.a, vector.b) != vector.unReference) {
50 return false;
51 }
52 return true;
53}
10const impl = @import("comparef.zig");
11const Order = impl.Order;
12const cmp_f64 = impl.cmp_f64;
13const unord_f64 = impl.unord_f64;
5414
5515const arguments = [_]f64{
5616 std.math.nan(f64),
......@@ -73,36 +33,20 @@ const arguments = [_]f64{
7333 std.math.inf(f64),
7434};
7535
76fn generateVector(comptime a: f64, comptime b: f64) TestVector {
77 const leResult = if (a < b) -1 else if (a == b) 0 else 1;
78 const geResult = if (a > b) 1 else if (a == b) 0 else -1;
79 const unResult = if (a != a or b != b) 1 else 0;
80 return TestVector{
81 .a = a,
82 .b = b,
83 .eqReference = leResult,
84 .geReference = geResult,
85 .gtReference = geResult,
86 .leReference = leResult,
87 .ltReference = leResult,
88 .neReference = leResult,
89 .unReference = unResult,
90 };
91}
92
93const test_vectors = init: {
94 @setEvalBranchQuota(10000);
95 var vectors: [arguments.len * arguments.len]TestVector = undefined;
36test "compare f64" {
9637 for (arguments[0..], 0..) |arg_i, i| {
9738 for (arguments[0..], 0..) |arg_j, j| {
98 vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
39 const expected_unord = i == 0 or j == 0;
40 const expected_order: ?Order = if (expected_unord) null else switch (std.math.order(
41 if (i >= 9) i - 1 else i,
42 if (j >= 9) j - 1 else j,
43 )) {
44 .lt => .lt,
45 .eq => .eq,
46 .gt => .gt,
47 };
48 try std.testing.expect(expected_order == cmp_f64(arg_i, arg_j));
49 try std.testing.expect(expected_unord == unord_f64(arg_i, arg_j));
9950 }
10051 }
101 break :init vectors;
102};
103
104test "compare f64" {
105 for (test_vectors) |vector| {
106 try std.testing.expect(test__cmpdf2(vector));
107 }
10852}
lib/compiler_rt/comparef.zig+274-167
......@@ -1,163 +1,309 @@
1const builtin = @import("builtin");
12const std = @import("std");
23
34const compiler_rt = @import("../compiler_rt.zig");
45const symbol = compiler_rt.symbol;
56
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_fcmpun, "__aeabi_fcmpun");
9 } else {
10 symbol(&__unordsf2, "__unordsf2");
11 }
12
13 symbol(&__unordxf2, "__unordxf2");
7const Unordered = if (builtin.cpu.arch == .avr)
8 i8
9else if (builtin.cpu.arch.isAARCH64())
10 i32
11else if (builtin.target.cTypeBitSize(.long).? >= builtin.target.ptrBitWidth())
12 c_long
13else
14 c_longlong;
15pub const Order = enum(Unordered) { lt = -1, eq = 0, gt = 1 };
16const SparcOrder = enum(i32) { eq = 0, lt = 1, gt = 2, un = 3 };
1417
15 symbol(&__eqhf2, "__eqhf2");
16 symbol(&__nehf2, "__nehf2");
17 symbol(&__lehf2, "__lehf2");
18comptime {
1819 symbol(&__cmphf2, "__cmphf2");
19 symbol(&__lthf2, "__lthf2");
20 symbol(&__cmphf2, "__eqhf2");
21 symbol(&__cmphf2, "__nehf2");
22 symbol(&__cmphf2, "__lthf2");
23 symbol(&__cmphf2, "__lehf2");
24 symbol(&__gehf2, "__gthf2");
25 symbol(&__gehf2, "__gehf2");
26 symbol(&__unordhf2, "__unordhf2");
2027
2128 if (compiler_rt.want_aeabi) {
2229 symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq");
2330 symbol(&__aeabi_fcmplt, "__aeabi_fcmplt");
2431 symbol(&__aeabi_fcmple, "__aeabi_fcmple");
32 symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt");
33 symbol(&__aeabi_fcmpge, "__aeabi_fcmpge");
34 symbol(&__aeabi_fcmpun, "__aeabi_fcmpun");
35
36 symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq");
37 symbol(&__aeabi_dcmplt, "__aeabi_dcmplt");
38 symbol(&__aeabi_dcmple, "__aeabi_dcmple");
39 symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt");
40 symbol(&__aeabi_dcmpge, "__aeabi_dcmpge");
41 symbol(&__aeabi_dcmpun, "__aeabi_dcmpun");
2542 } else {
26 symbol(&__eqsf2, "__eqsf2");
27 symbol(&__nesf2, "__nesf2");
28 symbol(&__lesf2, "__lesf2");
2943 symbol(&__cmpsf2, "__cmpsf2");
30 symbol(&__ltsf2, "__ltsf2");
44 symbol(&__cmpsf2, "__eqsf2");
45 symbol(&__cmpsf2, "__nesf2");
46 symbol(&__cmpsf2, "__ltsf2");
47 symbol(&__cmpsf2, "__lesf2");
48 symbol(&__gesf2, "__gtsf2");
49 symbol(&__gesf2, "__gesf2");
50 symbol(&__unordsf2, "__unordsf2");
51
52 symbol(&__cmpdf2, "__cmpdf2");
53 symbol(&__cmpdf2, "__eqdf2");
54 symbol(&__cmpdf2, "__nedf2");
55 symbol(&__cmpdf2, "__ltdf2");
56 symbol(&__cmpdf2, "__ledf2");
57 symbol(&__gedf2, "__gtdf2");
58 symbol(&__gedf2, "__gedf2");
59 symbol(&__unorddf2, "__unorddf2");
3160 }
3261
62 symbol(&__cmpxf2, "__cmpxf2");
63 symbol(&__cmpxf2, "__eqxf2");
64 symbol(&__cmpxf2, "__nexf2");
65 symbol(&__cmpxf2, "__ltxf2");
66 symbol(&__cmpxf2, "__lexf2");
67 symbol(&__gexf2, "__gtxf2");
68 symbol(&__gexf2, "__gexf2");
69 symbol(&__unordxf2, "__unordxf2");
70
3371 if (compiler_rt.want_ppc_abi) {
72 symbol(&__cmptf2, "__eqkf2");
73 symbol(&__cmptf2, "__nekf2");
74 symbol(&__cmptf2, "__ltkf2");
75 symbol(&__cmptf2, "__lekf2");
76 symbol(&__getf2, "__gtkf2");
77 symbol(&__getf2, "__gekf2");
3478 symbol(&__unordtf2, "__unordkf2");
79 } else if (compiler_rt.want_sparc64_abi) {
80 symbol(&_Qp_cmp, "_Qp_cmp");
81 symbol(&_Qp_feq, "_Qp_feq");
82 symbol(&_Qp_fne, "_Qp_fne");
83 symbol(&_Qp_flt, "_Qp_flt");
84 symbol(&_Qp_fle, "_Qp_fle");
85 symbol(&_Qp_fgt, "_Qp_fgt");
86 symbol(&_Qp_fge, "_Qp_fge");
87 } else if (compiler_rt.want_sparc32_abi) {
88 symbol(&_Q_cmp, "_Q_cmp");
89 symbol(&_Q_feq, "_Q_feq");
90 symbol(&_Q_fne, "_Q_fne");
91 symbol(&_Q_flt, "_Q_flt");
92 symbol(&_Q_fle, "_Q_fle");
93 symbol(&_Q_fgt, "_Q_fgt");
94 symbol(&_Q_fge, "_Q_fge");
95 } else {
96 symbol(&__cmptf2, "__cmptf2");
97 symbol(&__cmptf2, "__eqtf2");
98 symbol(&__cmptf2, "__netf2");
99 symbol(&__cmptf2, "__lttf2");
100 symbol(&__cmptf2, "__letf2");
101 symbol(&__getf2, "__gttf2");
102 symbol(&__getf2, "__getf2");
103 symbol(&__unordtf2, "__unordtf2");
35104 }
36 symbol(&__unordtf2, "__unordtf2");
37 symbol(&__unordhf2, "__unordhf2");
38}
39
40pub fn __unordhf2(a: f16, b: f16) callconv(.c) i32 {
41 return unordcmp(f16, a, b);
42105}
43106
44pub fn __unordtf2(a: f128, b: f128) callconv(.c) i32 {
45 return unordcmp(f128, a, b);
107fn __cmphf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order {
108 return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .gt;
46109}
47
48/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
49/// if a is greater than b, they return 1; and if a and b are equal they return 0.
50/// If either argument is NaN they return 1..."
51///
52/// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`,
53/// and `__ltsf2`.
54fn __cmpsf2(a: f32, b: f32) callconv(.c) i32 {
55 return @backingInt(cmpf2(f32, LE, a, b));
110fn __gehf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order {
111 return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .lt;
56112}
57
58/// "These functions return a value less than or equal to zero if neither argument is NaN,
59/// and a is less than or equal to b."
60pub fn __lesf2(a: f32, b: f32) callconv(.c) i32 {
61 return __cmpsf2(a, b);
113fn __unordhf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Unordered {
114 return @intFromBool(unord_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
62115}
63
64/// "These functions return zero if neither argument is NaN, and a and b are equal."
65/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined
66/// to have the same return value.
67pub fn __eqsf2(a: f32, b: f32) callconv(.c) i32 {
68 return __cmpsf2(a, b);
116pub fn cmp_f16(a: f16, b: f16) ?Order {
117 return cmpf2(f16, a, b);
69118}
70
71/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
72/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined
73/// to have the same return value.
74pub fn __nesf2(a: f32, b: f32) callconv(.c) i32 {
75 return __cmpsf2(a, b);
119pub fn unord_f16(a: f16, b: f16) bool {
120 return unord(f16, a, b);
76121}
77122
78/// "These functions return a value less than zero if neither argument is NaN, and a
79/// is strictly less than b."
80pub fn __ltsf2(a: f32, b: f32) callconv(.c) i32 {
81 return __cmpsf2(a, b);
123fn __cmpsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order {
124 return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .gt;
82125}
83
84126fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
85 return @intFromBool(cmpf2(f32, LE, a, b) == .Equal);
127 return @intFromBool(cmp_f32(a, b) == .eq);
86128}
87
88129fn __aeabi_fcmplt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
89 return @intFromBool(cmpf2(f32, LE, a, b) == .Less);
130 return @intFromBool(cmp_f32(a, b) == .lt);
90131}
91
92132fn __aeabi_fcmple(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
93 return @intFromBool(cmpf2(f32, LE, a, b) != .Greater);
133 return @intFromBool(cmp_f32(a, b) orelse .gt != .gt);
94134}
95
96/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
97/// if a is greater than b, they return 1; and if a and b are equal they return 0.
98/// If either argument is NaN they return 1..."
99///
100/// Note that this matches the definition of `__lehf2`, `__eqhf2`, `__nehf2`, `__cmphf2`,
101/// and `__lthf2`.
102fn __cmphf2(a: f16, b: f16) callconv(.c) i32 {
103 return @backingInt(cmpf2(f16, LE, a, b));
135fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order {
136 return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt;
104137}
105
106/// "These functions return a value less than or equal to zero if neither argument is NaN,
107/// and a is less than or equal to b."
108fn __lehf2(a: f16, b: f16) callconv(.c) i32 {
109 return __cmphf2(a, b);
138fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
139 return @intFromBool(cmp_f32(a, b) orelse .lt != .lt);
110140}
111
112/// "These functions return zero if neither argument is NaN, and a and b are equal."
113/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined
114/// to have the same return value.
115fn __eqhf2(a: f16, b: f16) callconv(.c) i32 {
116 return __cmphf2(a, b);
141fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
142 return @intFromBool(cmp_f32(a, b) == .gt);
117143}
118
119/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
120/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined
121/// to have the same return value.
122fn __nehf2(a: f16, b: f16) callconv(.c) i32 {
123 return __cmphf2(a, b);
144fn __unordsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Unordered {
145 return @intFromBool(unord_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
124146}
125
126/// "These functions return a value less than zero if neither argument is NaN, and a
127/// is strictly less than b."
128fn __lthf2(a: f16, b: f16) callconv(.c) i32 {
129 return __cmphf2(a, b);
147fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
148 return @intFromBool(unord_f32(a, b));
130149}
131
132fn __unordxf2(a: f80, b: f80) callconv(.c) i32 {
133 return unordcmp(f80, a, b);
150pub fn cmp_f32(a: f32, b: f32) ?Order {
151 return cmpf2(f32, a, b);
152}
153pub fn unord_f32(a: f32, b: f32) bool {
154 return unord(f32, a, b);
134155}
135156
136pub fn __unordsf2(a: f32, b: f32) callconv(.c) i32 {
137 return unordcmp(f32, a, b);
157fn __cmpdf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order {
158 return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .gt;
159}
160fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
161 return @intFromBool(cmp_f64(a, b) == .eq);
162}
163fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
164 return @intFromBool(cmp_f64(a, b) == .lt);
165}
166fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
167 return @intFromBool(cmp_f64(a, b) orelse .gt != .gt);
168}
169fn __gedf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order {
170 return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .lt;
171}
172fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
173 return @intFromBool(cmp_f64(a, b) orelse .lt != .lt);
174}
175fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
176 return @intFromBool(cmp_f64(a, b) == .gt);
177}
178fn __unorddf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Unordered {
179 return @intFromBool(unord_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
180}
181fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
182 return @intFromBool(unord_f64(a, b));
183}
184pub fn cmp_f64(a: f64, b: f64) ?Order {
185 return cmpf2(f64, a, b);
186}
187pub fn unord_f64(a: f64, b: f64) bool {
188 return unord(f64, a, b);
138189}
139190
140fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
141 return unordcmp(f32, a, b);
191fn __cmpxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order {
192 return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .gt;
193}
194fn __gexf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order {
195 return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .lt;
142196}
197fn __unordxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Unordered {
198 return @intFromBool(unord_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
199}
200pub fn cmp_f80(a: f80, b: f80) ?Order {
201 const a_rep = std.math.F80.fromFloat(a);
202 const b_rep = std.math.F80.fromFloat(b);
203 const sig_bits = std.math.floatMantissaBits(f80);
204 const int_bit = 0x8000000000000000;
205 const sign_bit = 0x8000;
206 const special_exp = 0x7FFF;
143207
144pub const LE = enum(i32) {
145 Less = -1,
146 Equal = 0,
147 Greater = 1,
208 // If either a or b is NaN, they are unordered.
209 if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
210 (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
211 return null;
148212
149 const Unordered: LE = .Greater;
150};
213 // If a and b are both zeros, they are equal.
214 if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0)
215 return .eq;
151216
152pub const GE = enum(i32) {
153 Less = -1,
154 Equal = 0,
155 Greater = 1,
217 if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) {
218 return .eq;
219 } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
220 // signs are different
221 if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) {
222 return .lt;
223 } else {
224 return .gt;
225 }
226 } else {
227 const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits);
228 const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits);
229 if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) {
230 return .lt;
231 } else {
232 return .gt;
233 }
234 }
235}
236pub fn unord_f80(a: f80, b: f80) bool {
237 return unord(f80, a, b);
238}
156239
157 const Unordered: GE = .Less;
158};
240fn __cmptf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order {
241 return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .gt;
242}
243fn __getf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order {
244 return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .lt;
245}
246fn __unordtf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Unordered {
247 return @intFromBool(unord_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
248}
249fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) SparcOrder {
250 return switch (cmp_f128(a.*, b.*) orelse return .un) {
251 .lt => .lt,
252 .eq => .eq,
253 .gt => .gt,
254 };
255}
256fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) i32 {
257 return @intFromBool(cmp_f128(a.*, b.*) == .eq);
258}
259fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) i32 {
260 return @intFromBool(cmp_f128(a.*, b.*) != .eq);
261}
262fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) i32 {
263 return @intFromBool(cmp_f128(a.*, b.*) == .lt);
264}
265fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) i32 {
266 return @intFromBool((cmp_f128(a.*, b.*) orelse .gt) != .gt);
267}
268fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) i32 {
269 return @intFromBool(cmp_f128(a.*, b.*) == .gt);
270}
271fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) i32 {
272 return @intFromBool((cmp_f128(a.*, b.*) orelse .lt) != .lt);
273}
274fn _Q_cmp(a: f128, b: f128) callconv(.c) SparcOrder {
275 return switch (cmp_f128(a, b) orelse return .un) {
276 .lt => .lt,
277 .eq => .eq,
278 .gt => .gt,
279 };
280}
281fn _Q_feq(a: f128, b: f128) callconv(.c) i32 {
282 return @intFromBool(cmp_f128(a, b) == .eq);
283}
284fn _Q_fne(a: f128, b: f128) callconv(.c) i32 {
285 return @intFromBool(cmp_f128(a, b) != .eq);
286}
287fn _Q_flt(a: f128, b: f128) callconv(.c) i32 {
288 return @intFromBool(cmp_f128(a, b) == .lt);
289}
290fn _Q_fle(a: f128, b: f128) callconv(.c) i32 {
291 return @intFromBool((cmp_f128(a, b) orelse .gt) != .gt);
292}
293fn _Q_fgt(a: f128, b: f128) callconv(.c) i32 {
294 return @intFromBool(cmp_f128(a, b) == .gt);
295}
296fn _Q_fge(a: f128, b: f128) callconv(.c) i32 {
297 return @intFromBool((cmp_f128(a, b) orelse .lt) != .lt);
298}
299pub fn cmp_f128(a: f128, b: f128) ?Order {
300 return cmpf2(f128, a, b);
301}
302pub fn unord_f128(a: f128, b: f128) bool {
303 return unord(f128, a, b);
304}
159305
160pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT {
306inline fn cmpf2(comptime T: type, a: T, b: T) ?Order {
161307 const bits = @typeInfo(T).float.bits;
162308 const srep_t = @Int(.signed, bits);
163309 const rep_t = @Int(.unsigned, bits);
......@@ -175,81 +321,42 @@ pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT {
175321 const bAbs = @as(rep_t, @bitCast(bInt)) & absMask;
176322
177323 // If either a or b is NaN, they are unordered.
178 if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
324 if (aAbs > infRep or bAbs > infRep) return null;
179325
180326 // If a and b are both zeros, they are equal.
181 if ((aAbs | bAbs) == 0) return .Equal;
327 if ((aAbs | bAbs) == 0) return .eq;
182328
183329 // If at least one of a and b is positive, we get the same result comparing
184330 // a and b as signed integers as we would with a floating-point compare.
185331 if ((aInt & bInt) >= 0) {
186332 if (aInt < bInt) {
187 return .Less;
333 return .lt;
188334 } else if (aInt == bInt) {
189 return .Equal;
190 } else return .Greater;
335 return .eq;
336 } else return .gt;
191337 } else {
192338 // Otherwise, both are negative, so we need to flip the sense of the
193339 // comparison to get the correct result. (This assumes a twos- or ones-
194340 // complement integer representation; if integers are represented in a
195341 // sign-magnitude representation, then this flip is incorrect).
196342 if (aInt > bInt) {
197 return .Less;
343 return .lt;
198344 } else if (aInt == bInt) {
199 return .Equal;
200 } else return .Greater;
345 return .eq;
346 } else return .gt;
201347 }
202348}
203349
204pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT {
205 const a_rep = std.math.F80.fromFloat(a);
206 const b_rep = std.math.F80.fromFloat(b);
207 const sig_bits = std.math.floatMantissaBits(f80);
208 const int_bit = 0x8000000000000000;
209 const sign_bit = 0x8000;
210 const special_exp = 0x7FFF;
211
212 // If either a or b is NaN, they are unordered.
213 if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
214 (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
215 return RT.Unordered;
216
217 // If a and b are both zeros, they are equal.
218 if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0)
219 return .Equal;
220
221 if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) {
222 return .Equal;
223 } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
224 // signs are different
225 if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) {
226 return .Less;
227 } else {
228 return .Greater;
229 }
230 } else {
231 const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits);
232 const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits);
233 if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) {
234 return .Less;
235 } else {
236 return .Greater;
237 }
238 }
239}
240
241test "cmp_f80" {
242 inline for (.{ LE, GE }) |RT| {
243 try std.testing.expect(cmp_f80(RT, 1.0, 1.0) == RT.Equal);
244 try std.testing.expect(cmp_f80(RT, 0.0, -0.0) == RT.Equal);
245 try std.testing.expect(cmp_f80(RT, 2.0, 4.0) == RT.Less);
246 try std.testing.expect(cmp_f80(RT, 2.0, -4.0) == RT.Greater);
247 try std.testing.expect(cmp_f80(RT, -2.0, -4.0) == RT.Greater);
248 try std.testing.expect(cmp_f80(RT, -2.0, 4.0) == RT.Less);
249 }
350test cmp_f80 {
351 try std.testing.expect(cmp_f80(1.0, 1.0) == .eq);
352 try std.testing.expect(cmp_f80(0.0, -0.0) == .eq);
353 try std.testing.expect(cmp_f80(2.0, 4.0) == .lt);
354 try std.testing.expect(cmp_f80(2.0, -4.0) == .gt);
355 try std.testing.expect(cmp_f80(-2.0, -4.0) == .gt);
356 try std.testing.expect(cmp_f80(-2.0, 4.0) == .lt);
250357}
251358
252pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
359inline fn unord(comptime T: type, a: T, b: T) bool {
253360 const rep_t = @Int(.unsigned, @typeInfo(T).float.bits);
254361
255362 const significandBits = std.math.floatMantissaBits(T);
......@@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
261368 const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask;
262369 const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask;
263370
264 return @intFromBool(aAbs > infRep or bAbs > infRep);
371 return aAbs > infRep or bAbs > infRep;
265372}
266373
267374test {
lib/compiler_rt/comparesf2_test.zig+17-73
......@@ -5,52 +5,12 @@
55const std = @import("std");
66const builtin = @import("builtin");
77
8const __eqsf2 = @import("./comparef.zig").__eqsf2;
9const __lesf2 = @import("./comparef.zig").__lesf2;
10const __ltsf2 = @import("./comparef.zig").__ltsf2;
11const __nesf2 = @import("./comparef.zig").__nesf2;
8const compiler_rt = @import("../compiler_rt.zig");
129
13const __gesf2 = @import("./gesf2.zig").__gesf2;
14const __gtsf2 = @import("./gesf2.zig").__gtsf2;
15
16const __unordsf2 = @import("./comparef.zig").__unordsf2;
17
18const TestVector = struct {
19 a: f32,
20 b: f32,
21 eqReference: c_int,
22 geReference: c_int,
23 gtReference: c_int,
24 leReference: c_int,
25 ltReference: c_int,
26 neReference: c_int,
27 unReference: c_int,
28};
29
30fn test__cmpsf2(vector: TestVector) bool {
31 if (__eqsf2(vector.a, vector.b) != vector.eqReference) {
32 return false;
33 }
34 if (__gesf2(vector.a, vector.b) != vector.geReference) {
35 return false;
36 }
37 if (__gtsf2(vector.a, vector.b) != vector.gtReference) {
38 return false;
39 }
40 if (__lesf2(vector.a, vector.b) != vector.leReference) {
41 return false;
42 }
43 if (__ltsf2(vector.a, vector.b) != vector.ltReference) {
44 return false;
45 }
46 if (__nesf2(vector.a, vector.b) != vector.neReference) {
47 return false;
48 }
49 if (__unordsf2(vector.a, vector.b) != vector.unReference) {
50 return false;
51 }
52 return true;
53}
10const impl = @import("comparef.zig");
11const Order = impl.Order;
12const cmp_f32 = impl.cmp_f32;
13const unord_f32 = impl.unord_f32;
5414
5515const arguments = [_]f32{
5616 std.math.nan(f32),
......@@ -73,36 +33,20 @@ const arguments = [_]f32{
7333 std.math.inf(f32),
7434};
7535
76fn generateVector(comptime a: f32, comptime b: f32) TestVector {
77 const leResult = if (a < b) -1 else if (a == b) 0 else 1;
78 const geResult = if (a > b) 1 else if (a == b) 0 else -1;
79 const unResult = if (a != a or b != b) 1 else 0;
80 return TestVector{
81 .a = a,
82 .b = b,
83 .eqReference = leResult,
84 .geReference = geResult,
85 .gtReference = geResult,
86 .leReference = leResult,
87 .ltReference = leResult,
88 .neReference = leResult,
89 .unReference = unResult,
90 };
91}
92
93const test_vectors = init: {
94 @setEvalBranchQuota(10000);
95 var vectors: [arguments.len * arguments.len]TestVector = undefined;
36test "compare f32" {
9637 for (arguments[0..], 0..) |arg_i, i| {
9738 for (arguments[0..], 0..) |arg_j, j| {
98 vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j);
39 const expected_unord = i == 0 or j == 0;
40 const expected_order: ?Order = if (expected_unord) null else switch (std.math.order(
41 i - @intFromBool(i >= 9),
42 j - @intFromBool(j >= 9),
43 )) {
44 .lt => .lt,
45 .eq => .eq,
46 .gt => .gt,
47 };
48 try std.testing.expect(expected_order == cmp_f32(arg_i, arg_j));
49 try std.testing.expect(expected_unord == unord_f32(arg_i, arg_j));
9950 }
10051 }
101 break :init vectors;
102};
103
104test "compare f32" {
105 for (test_vectors) |vector| {
106 try std.testing.expect(test__cmpsf2(vector));
107 }
10852}
lib/compiler_rt/cos.zig+64-51
......@@ -13,31 +13,34 @@ const expect = std.testing.expect;
1313const expectApproxEqAbs = std.testing.expectApproxEqAbs;
1414
1515const compiler_rt = @import("../compiler_rt.zig");
16const symbol = @import("../compiler_rt.zig").symbol;
16const symbol = compiler_rt.symbol;
1717const trig = @import("trig.zig");
1818const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
1919const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
2020const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
2222comptime {
23 symbol(&cosh, "__cosh");
24 symbol(&cosl, "__cosl");
23 symbol(&__cosh, "__cosh");
2524 symbol(&cosf, "cosf");
2625 symbol(&cos, "cos");
27 symbol(&cosx, "__cosx");
28 if (compiler_rt.want_ppc_abi) {
29 symbol(&cosq, "cosf128");
30 }
31 symbol(&cosq, "cosq");
26 symbol(&__cosx, "__cosx");
27 symbol(&cosq, "cosf128");
3228 symbol(&cosl, "cosl");
29 symbol(&cosl, "__cosl"); // required by musl
3330}
3431
35pub fn cosh(a: f16) callconv(.c) f16 {
32fn __cosh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
33 return compiler_rt.f16.toAbi(cos_f16(compiler_rt.f16.fromAbi(x)));
34}
35pub fn cos_f16(x: f16) f16 {
3636 // TODO: more efficient implementation
37 return @floatCast(cosf(a));
37 return @floatCast(cos_f32(x));
3838}
3939
40pub fn cosf(x: f32) callconv(.c) f32 {
40fn cosf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
41 return compiler_rt.f32.toAbi(cos_f32(compiler_rt.f32.fromAbi(x)));
42}
43pub fn cos_f32(x: f32) f32 {
4144 // Small multiples of pi/2 rounded to double precision.
4245 const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
4346 const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
......@@ -94,7 +97,10 @@ pub fn cosf(x: f32) callconv(.c) f32 {
9497 };
9598}
9699
97pub fn cos(x: f64) callconv(.c) f64 {
100fn cos(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
101 return compiler_rt.f64.toAbi(cos_f64(compiler_rt.f64.fromAbi(x)));
102}
103pub fn cos_f64(x: f64) f64 {
98104 var ix = @as(u64, @bitCast(x)) >> 32;
99105 ix &= 0x7fffffff;
100106
......@@ -123,7 +129,10 @@ pub fn cos(x: f64) callconv(.c) f64 {
123129 };
124130}
125131
126pub fn cosx(x: f80) callconv(.c) f80 {
132fn __cosx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
133 return compiler_rt.f80.toAbi(cos_f80(compiler_rt.f80.fromAbi(x)));
134}
135pub fn cos_f80(x: f80) f80 {
127136 const se = ld.signExponent(x) & 0x7fff;
128137 if (se == 0x7fff) {
129138 return x - x;
......@@ -147,7 +156,10 @@ pub fn cosx(x: f80) callconv(.c) f80 {
147156 };
148157}
149158
150pub fn cosq(x: f128) callconv(.c) f128 {
159fn cosq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
160 return compiler_rt.f128.toAbi(cos_f128(compiler_rt.f128.fromAbi(x)));
161}
162pub fn cos_f128(x: f128) f128 {
151163 const se = ld.signExponent(x) & 0x7fff;
152164 if (se == 0x7fff) {
153165 return x - x;
......@@ -173,20 +185,21 @@ pub fn cosq(x: f128) callconv(.c) f128 {
173185
174186pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble {
175187 switch (@typeInfo(c_longdouble).float.bits) {
176 64 => return cos(x),
177 80 => return cosx(x),
178 128 => return cosq(x),
179 else => @compileError("unreachable"),
188 64 => return cos_f64(x),
189 80 => return cos_f80(x),
190 128 => return cos_f128(x),
191 else => comptime unreachable,
180192 }
181193}
182194
183195fn testCosSpecial(comptime T: type) !void {
184196 const f = switch (T) {
185 f32 => cosf,
186 f64 => cos,
187 f80 => cosx,
188 f128 => cosq,
189 else => @compileError("unimplemented"),
197 f16 => cos_f16,
198 f32 => cos_f32,
199 f64 => cos_f64,
200 f80 => cos_f80,
201 f128 => cos_f128,
202 else => comptime unreachable,
190203 };
191204
192205 try expect(f(0.0) == 1.0);
......@@ -198,13 +211,13 @@ fn testCosSpecial(comptime T: type) !void {
198211
199212test "cos32.normal" {
200213 const epsilon = math.floatEps(f32);
201 try expectApproxEqAbs(@as(f32, 1.0), cosf(0.0), epsilon);
202 try expectApproxEqAbs(@as(f32, 0.9800666), cosf(0.2), epsilon);
203 try expectApproxEqAbs(@as(f32, 0.6276231), cosf(0.8923), epsilon);
204 try expectApproxEqAbs(@as(f32, 0.0707372), cosf(1.5), epsilon);
205 try expectApproxEqAbs(@as(f32, 0.0707372), cosf(-1.5), epsilon);
206 try expectApproxEqAbs(@as(f32, 0.96913195), cosf(37.45), epsilon);
207 try expectApproxEqAbs(@as(f32, 0.40079966), cosf(89.123), epsilon);
214 try expectApproxEqAbs(@as(f32, 1.0), cos_f32(0.0), epsilon);
215 try expectApproxEqAbs(@as(f32, 0.9800666), cos_f32(0.2), epsilon);
216 try expectApproxEqAbs(@as(f32, 0.6276231), cos_f32(0.8923), epsilon);
217 try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(1.5), epsilon);
218 try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(-1.5), epsilon);
219 try expectApproxEqAbs(@as(f32, 0.96913195), cos_f32(37.45), epsilon);
220 try expectApproxEqAbs(@as(f32, 0.40079966), cos_f32(89.123), epsilon);
208221}
209222
210223test "cos32.special" {
......@@ -213,13 +226,13 @@ test "cos32.special" {
213226
214227test "cos64.normal" {
215228 const epsilon = math.floatEps(f64);
216 try expectApproxEqAbs(@as(f64, 1.0), cos(0.0), epsilon);
217 try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos(0.2), epsilon);
218 try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos(0.8923), epsilon);
219 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(1.5), epsilon);
220 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(-1.5), epsilon);
221 try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos(37.45), epsilon);
222 try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos(89.123), epsilon);
229 try expectApproxEqAbs(@as(f64, 1.0), cos_f64(0.0), epsilon);
230 try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos_f64(0.2), epsilon);
231 try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos_f64(0.8923), epsilon);
232 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(1.5), epsilon);
233 try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(-1.5), epsilon);
234 try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos_f64(37.45), epsilon);
235 try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos_f64(89.123), epsilon);
223236}
224237
225238test "cos64.special" {
......@@ -228,13 +241,13 @@ test "cos64.special" {
228241
229242test "cos80.normal" {
230243 const epsilon = math.floatEps(f80);
231 try expectApproxEqAbs(@as(f80, 1.0), cosx(0.0), epsilon);
232 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cosx(0.2), epsilon);
233 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cosx(0.8923), epsilon);
234 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(1.5), epsilon);
235 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(-1.5), epsilon);
236 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cosx(37.45), epsilon);
237 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cosx(89.123), epsilon);
244 try expectApproxEqAbs(@as(f80, 1.0), cos_f80(0.0), epsilon);
245 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cos_f80(0.2), epsilon);
246 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cos_f80(0.8923), epsilon);
247 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(1.5), epsilon);
248 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(-1.5), epsilon);
249 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cos_f80(37.45), epsilon);
250 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cos_f80(89.123), epsilon);
238251}
239252
240253test "cos80.special" {
......@@ -243,13 +256,13 @@ test "cos80.special" {
243256
244257test "cos128.normal" {
245258 const epsilon = math.floatEps(f128);
246 try expectApproxEqAbs(@as(f128, 1.0), cosq(0.0), epsilon);
247 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cosq(0.2), epsilon);
248 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cosq(0.8923), epsilon);
249 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(1.5), epsilon);
250 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(-1.5), epsilon);
251 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cosq(37.45), epsilon);
252 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cosq(89.123), epsilon);
259 try expectApproxEqAbs(@as(f128, 1.0), cos_f128(0.0), epsilon);
260 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cos_f128(0.2), epsilon);
261 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cos_f128(0.8923), epsilon);
262 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(1.5), epsilon);
263 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(-1.5), epsilon);
264 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cos_f128(37.45), epsilon);
265 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cos_f128(89.123), epsilon);
253266}
254267
255268test "cos128.special" {
lib/compiler_rt/count0bits.zig+2-1
......@@ -1,6 +1,7 @@
11const builtin = @import("builtin");
22const std = @import("std");
3const symbol = @import("../compiler_rt.zig").symbol;
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45
56comptime {
67 symbol(&__clzsi2, "__clzsi2");
lib/compiler_rt/divc3.zig+78-5
......@@ -7,12 +7,81 @@ const maxInt = std.math.maxInt;
77const minInt = std.math.minInt;
88const isFinite = std.math.isFinite;
99const copysign = std.math.copysign;
10const Complex = @import("mulc3.zig").Complex;
10
11const compiler_rt = @import("../compiler_rt.zig");
12const symbol = compiler_rt.symbol;
13const Complex = compiler_rt.Complex;
14
15comptime {
16 if (@import("builtin").zig_backend != .stage2_c) {
17 symbol(&__divhc3, "__divhc3");
18 symbol(&__divsc3, "__divsc3");
19 symbol(&__divdc3, "__divdc3");
20 symbol(&__divxc3, "__divxc3");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&__divtc3, "__divkc3");
23 } else {
24 symbol(&__divtc3, "__divtc3");
25 }
26 }
27}
28
29fn __divhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi {
30 return compiler_rt.f16.complex.toAbi(div_cf16(
31 compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
32 compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
33 ));
34}
35pub fn div_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) {
36 return divc3(f16, a, b);
37}
38
39fn __divsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi {
40 return compiler_rt.f32.complex.toAbi(div_cf32(
41 compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
42 compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
43 ));
44}
45pub fn div_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) {
46 return divc3(f32, a, b);
47}
48
49fn __divdc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi {
50 return compiler_rt.f64.complex.toAbi(div_cf64(
51 compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
52 compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
53 ));
54}
55pub fn div_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) {
56 return divc3(f64, a, b);
57}
58
59fn __divxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi {
60 return compiler_rt.f80.complex.toAbi(div_cf80(
61 compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
62 compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
63 ));
64}
65pub fn div_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) {
66 return divc3(f80, a, b);
67}
68
69fn __divtc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi {
70 return compiler_rt.f128.complex.toAbi(div_cf128(
71 compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
72 compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
73 ));
74}
75pub fn div_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) {
76 return divc3(f128, a, b);
77}
1178
1279/// Implementation based on Annex G of C17 Standard (N2176)
13pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
14 var c = c_in;
15 var d = d_in;
80inline fn divc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) {
81 const a = lhs.real;
82 const b = lhs.imag;
83 var c = rhs.real;
84 var d = rhs.imag;
1685
1786 // logbw used to prevent under/over-flow
1887 const logbw = ilogb(@max(@abs(c), @abs(d)));
......@@ -23,7 +92,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
2392 break :b logbw;
2493 } else 0;
2594 const denom = c * c + d * d;
26 const result = Complex(T){
95 const result: Complex(T) = .{
2796 .real = scalbn((a * c + b * d) / denom, -ilogbw),
2897 .imag = scalbn((b * c - a * d) / denom, -ilogbw),
2998 };
......@@ -58,3 +127,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
58127
59128 return result;
60129}
130
131test {
132 _ = @import("divc3_test.zig");
133}
lib/compiler_rt/divc3_test.zig+28-51
......@@ -2,76 +2,53 @@ const std = @import("std");
22const math = std.math;
33const expect = std.testing.expect;
44
5const Complex = @import("./mulc3.zig").Complex;
6const __divhc3 = @import("./divhc3.zig").__divhc3;
7const __divsc3 = @import("./divsc3.zig").__divsc3;
8const __divdc3 = @import("./divdc3.zig").__divdc3;
9const __divxc3 = @import("./divxc3.zig").__divxc3;
10const __divtc3 = @import("./divtc3.zig").__divtc3;
5const Complex = @import("../compiler_rt.zig").Complex;
6
7const impl = @import("divc3.zig");
8const div_cf16 = impl.div_cf16;
9const div_cf32 = impl.div_cf32;
10const div_cf64 = impl.div_cf64;
11const div_cf80 = impl.div_cf80;
12const div_cf128 = impl.div_cf128;
1113
1214test "divc3" {
13 try testDiv(f16, __divhc3);
14 try testDiv(f32, __divsc3);
15 try testDiv(f64, __divdc3);
16 try testDiv(f80, __divxc3);
17 try testDiv(f128, __divtc3);
15 try testDiv(f16, div_cf16);
16 try testDiv(f32, div_cf32);
17 try testDiv(f64, div_cf64);
18 try testDiv(f80, div_cf80);
19 try testDiv(f128, div_cf128);
1820}
1921
20fn testDiv(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void {
22fn testDiv(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void {
2123 {
22 const a: T = 1.0;
23 const b: T = 0.0;
24 const c: T = -1.0;
25 const d: T = 0.0;
26
27 const result = f(a, b, c, d);
24 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 });
2825 try expect(result.real == -1.0);
29 try expect(result.imag == 0.0);
26 try expect(math.isNegativeZero(result.imag));
3027 }
3128 {
32 const a: T = 1.0;
33 const b: T = 0.0;
34 const c: T = -4.0;
35 const d: T = 0.0;
36
37 const result = f(a, b, c, d);
29 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 });
3830 try expect(result.real == -0.25);
39 try expect(result.imag == 0.0);
31 try expect(math.isNegativeZero(result.imag));
4032 }
4133 {
4234 // if the first operand is an infinity and the second operand is a finite number, then the
43 // result of the / operator is an infinity;
44 const a: T = -math.inf(T);
45 const b: T = 0.0;
46 const c: T = -4.0;
47 const d: T = 1.0;
48
49 const result = f(a, b, c, d);
50 try expect(result.real == math.inf(T));
51 try expect(result.imag == math.inf(T));
35 // resultult of the / operator is an infinity;
36 const result = f(.{ .real = -math.inf(T), .imag = 0.0 }, .{ .real = -4.0, .imag = 1.0 });
37 try expect(math.isPositiveInf(result.real));
38 try expect(math.isPositiveInf(result.imag));
5239 }
5340 {
5441 // if the first operand is a finite number and the second operand is an infinity, then the
5542 // result of the / operator is a zero;
56 const a: T = 17.2;
57 const b: T = 0.0;
58 const c: T = -math.inf(T);
59 const d: T = 0.0;
60
61 const result = f(a, b, c, d);
62 try expect(result.real == -0.0);
63 try expect(result.imag == 0.0);
43 const result = f(.{ .real = 17.2, .imag = 0.0 }, .{ .real = -math.inf(T), .imag = 0.0 });
44 try expect(math.isNegativeZero(result.real));
45 try expect(math.isNegativeZero(result.imag));
6446 }
6547 {
6648 // if the first operand is a nonzero finite number or an infinity and the second operand is
6749 // a zero, then the result of the / operator is an infinity
68 const a: T = 1.1;
69 const b: T = 0.1;
70 const c: T = 0.0;
71 const d: T = 0.0;
72
73 const result = f(a, b, c, d);
74 try expect(result.real == math.inf(T));
75 try expect(result.imag == math.inf(T));
50 const result = f(.{ .real = 1.1, .imag = 0.1 }, .{ .real = 0.0, .imag = 0.0 });
51 try expect(math.isPositiveInf(result.real));
52 try expect(math.isPositiveInf(result.imag));
7653 }
7754}
lib/compiler_rt/divdc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const divc3 = @import("./divc3.zig");
3const Complex = @import("./mulc3.zig").Complex;
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__divdc3, "__divdc3");
8 }
9}
10
11pub fn __divdc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) Complex(f64) {
12 return divc3.divc3(f64, a, b, c, d);
13}
lib/compiler_rt/divdf3.zig+4-4
......@@ -17,15 +17,15 @@ comptime {
1717 }
1818}
1919
20pub fn __divdf3(a: f64, b: f64) callconv(.c) f64 {
21 return div(a, b);
20fn __divdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
21 return compiler_rt.f64.toAbi(div_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
2222}
2323
2424fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
25 return div(a, b);
25 return div_f64(a, b);
2626}
2727
28inline fn div(a: f64, b: f64) f64 {
28pub fn div_f64(a: f64, b: f64) f64 {
2929 const Z = @Int(.unsigned, 64);
3030 const SignedZ = @Int(.signed, 64);
3131
lib/compiler_rt/divdf3_test.zig+2-2
......@@ -6,7 +6,7 @@ const std = @import("std");
66const math = std.math;
77const testing = std.testing;
88
9const __divdf3 = @import("divdf3.zig").__divdf3;
9const div_f64 = @import("divdf3.zig").div_f64;
1010
1111const nanRep: u64 = @as(u64, @bitCast(math.nan(f64)));
1212const infRep: u64 = @as(u64, @bitCast(math.inf(f64)));
......@@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool {
3030}
3131
3232fn test__divdf3(a: f64, b: f64, expected: u64) !void {
33 const x = __divdf3(a, b);
33 const x = div_f64(a, b);
3434 const ret = compareResultD(x, expected);
3535 try testing.expect(ret == true);
3636}
lib/compiler_rt/divhc3.zig deleted-14
......@@ -1,14 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const divc3 = @import("./divc3.zig");
4const Complex = @import("./mulc3.zig").Complex;
5
6comptime {
7 if (@import("builtin").zig_backend != .stage2_c) {
8 symbol(&__divhc3, "__divhc3");
9 }
10}
11
12pub fn __divhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) Complex(f16) {
13 return divc3.divc3(f16, a, b, c, d);
14}
lib/compiler_rt/divhf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const divsf3 = @import("./divsf3.zig");
3
4comptime {
5 symbol(&__divhf3, "__divhf3");
6}
7
8pub fn __divhf3(a: f16, b: f16) callconv(.c) f16 {
9 // TODO: more efficient implementation
10 return @floatCast(divsf3.__divsf3(a, b));
11}
lib/compiler_rt/divmodei4.zig+1-1
......@@ -5,7 +5,7 @@ const std = @import("std");
55
66const compiler_rt = @import("../compiler_rt.zig");
77const udivmod = @import("udivmodei4.zig").divmod;
8const symbol = @import("../compiler_rt.zig").symbol;
8const symbol = compiler_rt.symbol;
99
1010comptime {
1111 symbol(&__divei4, "__divei4");
lib/compiler_rt/divsc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const divc3 = @import("./divc3.zig");
2const Complex = @import("./mulc3.zig").Complex;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__divsc3, "__divsc3");
8 }
9}
10
11pub fn __divsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) Complex(f32) {
12 return divc3.divc3(f32, a, b, c, d);
13}
lib/compiler_rt/divsf3.zig+13-4
......@@ -9,6 +9,7 @@ const symbol = compiler_rt.symbol;
99const normalize = compiler_rt.normalize;
1010
1111comptime {
12 symbol(&__divhf3, "__divhf3");
1213 if (compiler_rt.want_aeabi) {
1314 symbol(&__aeabi_fdiv, "__aeabi_fdiv");
1415 } else {
......@@ -16,15 +17,23 @@ comptime {
1617 }
1718}
1819
19pub fn __divsf3(a: f32, b: f32) callconv(.c) f32 {
20 return div(a, b);
20fn __divhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
21 return compiler_rt.f16.toAbi(div_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
22}
23pub fn div_f16(a: f16, b: f16) f16 {
24 // TODO: more efficient implementation
25 return @floatCast(div_f32(a, b));
26}
27
28fn __divsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
29 return compiler_rt.f32.toAbi(div_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
2130}
2231
2332fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
24 return div(a, b);
33 return div_f32(a, b);
2534}
2635
27inline fn div(a: f32, b: f32) f32 {
36pub fn div_f32(a: f32, b: f32) f32 {
2837 const Z = @Int(.unsigned, 32);
2938
3039 const significandBits = std.math.floatMantissaBits(f32);
lib/compiler_rt/divsf3_test.zig+2-2
......@@ -6,7 +6,7 @@ const std = @import("std");
66const math = std.math;
77const testing = std.testing;
88
9const __divsf3 = @import("divsf3.zig").__divsf3;
9const div_f32 = @import("divsf3.zig").div_f32;
1010
1111const nanRep: u32 = @as(u32, @bitCast(math.nan(f32)));
1212const infRep: u32 = @as(u32, @bitCast(math.inf(f32)));
......@@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool {
3030}
3131
3232fn test__divsf3(a: f32, b: f32, expected: u32) !void {
33 const x = __divsf3(a, b);
33 const x = div_f32(a, b);
3434 const ret = compareResultF(x, expected);
3535 try testing.expect(ret == true);
3636}
lib/compiler_rt/divtc3.zig deleted-16
......@@ -1,16 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const divc3 = @import("./divc3.zig");
3const Complex = @import("./mulc3.zig").Complex;
4const symbol = @import("../compiler_rt.zig").symbol;
5
6comptime {
7 if (@import("builtin").zig_backend != .stage2_c) {
8 if (compiler_rt.want_ppc_abi)
9 symbol(&__divtc3, "__divkc3");
10 symbol(&__divtc3, "__divtc3");
11 }
12}
13
14pub fn __divtc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) Complex(f128) {
15 return divc3.divc3(f128, a, b, c, d);
16}
lib/compiler_rt/divtf3.zig+6-5
......@@ -13,19 +13,20 @@ comptime {
1313 symbol(&_Qp_div, "_Qp_div");
1414 } else if (compiler_rt.want_sparc32_abi) {
1515 symbol(&__divtf3, "_Q_div");
16 } else {
17 symbol(&__divtf3, "__divtf3");
1618 }
17 symbol(&__divtf3, "__divtf3");
1819}
1920
20pub fn __divtf3(a: f128, b: f128) callconv(.c) f128 {
21 return div(a, b);
21fn __divtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
22 return compiler_rt.f128.toAbi(div_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
2223}
2324
2425fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
25 c.* = div(a.*, b.*);
26 c.* = div_f128(a.*, b.*);
2627}
2728
28inline fn div(a: f128, b: f128) f128 {
29pub fn div_f128(a: f128, b: f128) f128 {
2930 const Z = @Int(.unsigned, 128);
3031
3132 const significandBits = std.math.floatMantissaBits(f128);
lib/compiler_rt/divtf3_test.zig+2-2
......@@ -2,7 +2,7 @@ const std = @import("std");
22const math = std.math;
33const testing = std.testing;
44
5const __divtf3 = @import("divtf3.zig").__divtf3;
5const div_f128 = @import("divtf3.zig").div_f128;
66
77fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
88 const rep: u128 = @bitCast(result);
......@@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
2424}
2525
2626fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void {
27 const x = __divtf3(a, b);
27 const x = div_f128(a, b);
2828 const ret = compareResultLD(x, expectedHi, expectedLo);
2929 try testing.expect(ret == true);
3030}
lib/compiler_rt/divxc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const divc3 = @import("./divc3.zig");
3const Complex = @import("./mulc3.zig").Complex;
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__divxc3, "__divxc3");
8 }
9}
10
11pub fn __divxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) Complex(f80) {
12 return divc3.divc3(f80, a, b, c, d);
13}
lib/compiler_rt/divxf3.zig+4-1
......@@ -11,7 +11,10 @@ comptime {
1111 symbol(&__divxf3, "__divxf3");
1212}
1313
14pub fn __divxf3(a: f80, b: f80) callconv(.c) f80 {
14fn __divxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
15 return compiler_rt.f80.toAbi(div_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
16}
17pub fn div_f80(a: f80, b: f80) f80 {
1518 const T = f80;
1619 const Z = @Int(.unsigned, @bitSizeOf(T));
1720
lib/compiler_rt/divxf3_test.zig+3-3
......@@ -2,7 +2,7 @@ const std = @import("std");
22const math = std.math;
33const testing = std.testing;
44
5const __divxf3 = @import("divxf3.zig").__divxf3;
5const div_f80 = @import("divxf3.zig").div_f80;
66
77const nanRep: u80 = @as(u80, @bitCast(math.nan(f80)));
88const infRep: u80 = @as(u80, @bitCast(math.inf(f80)));
......@@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool {
1919}
2020
2121fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void {
22 const x = __divxf3(a, b);
22 const x = div_f80(a, b);
2323 const ret = compareResult(x, expected);
2424 try testing.expect(ret == true);
2525}
2626
2727fn test__divxf3(a: f80, b: f80) !void {
2828 const integerBit = 1 << math.floatFractionalBits(f80);
29 const x = __divxf3(a, b);
29 const x = div_f80(a, b);
3030
3131 // Next float (assuming normal, non-zero result)
3232 const x_plus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit);
lib/compiler_rt/exp.zig+105-94
......@@ -14,26 +14,29 @@ const expect = std.testing.expect;
1414const expectEqual = std.testing.expectEqual;
1515
1616const compiler_rt = @import("../compiler_rt.zig");
17const symbol = @import("../compiler_rt.zig").symbol;
17const symbol = compiler_rt.symbol;
1818
1919comptime {
2020 symbol(&__exph, "__exph");
2121 symbol(&expf, "expf");
2222 symbol(&exp, "exp");
2323 symbol(&__expx, "__expx");
24 if (compiler_rt.want_ppc_abi) {
25 symbol(&expq, "expf128");
26 }
27 symbol(&expq, "expq");
24 symbol(&expq, "expf128");
2825 symbol(&expl, "expl");
2926}
3027
31pub fn __exph(a: f16) callconv(.c) f16 {
28fn __exph(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
29 return compiler_rt.f16.toAbi(exp_f16(compiler_rt.f16.fromAbi(x)));
30}
31pub fn exp_f16(x: f16) f16 {
3232 // TODO: more efficient implementation
33 return @floatCast(expf(a));
33 return @floatCast(exp_f32(x));
3434}
3535
36pub fn expf(x_: f32) callconv(.c) f32 {
36fn expf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
37 return compiler_rt.f32.toAbi(exp_f32(compiler_rt.f32.fromAbi(x)));
38}
39pub fn exp_f32(x_: f32) f32 {
3740 const half = [_]f32{ 0.5, -0.5 };
3841 const ln2hi = 6.9314575195e-1;
3942 const ln2lo = 1.4286067653e-6;
......@@ -108,7 +111,10 @@ pub fn expf(x_: f32) callconv(.c) f32 {
108111 }
109112}
110113
111pub fn exp(x_: f64) callconv(.c) f64 {
114fn exp(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
115 return compiler_rt.f64.toAbi(exp_f64(compiler_rt.f64.fromAbi(x)));
116}
117pub fn exp_f64(x_: f64) f64 {
112118 const half = [_]f64{ 0.5, -0.5 };
113119 const ln2hi: f64 = 6.93147180369123816490e-01;
114120 const ln2lo: f64 = 1.90821492927058770002e-10;
......@@ -189,116 +195,121 @@ pub fn exp(x_: f64) callconv(.c) f64 {
189195 }
190196}
191197
192pub fn __expx(a: f80) callconv(.c) f80 {
198fn __expx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
199 return compiler_rt.f80.toAbi(exp_f80(compiler_rt.f80.fromAbi(x)));
200}
201pub fn exp_f80(x: f80) f80 {
193202 // TODO: more efficient implementation
194 return @floatCast(expq(a));
203 return @floatCast(exp_f128(x));
195204}
196205
197const expq = @import("exp_f128.zig").exp;
206fn expq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
207 return compiler_rt.f128.toAbi(exp_f128(compiler_rt.f128.fromAbi(x)));
208}
209pub const exp_f128 = @import("exp_f128.zig").exp;
198210
199211pub fn expl(x: c_longdouble) callconv(.c) c_longdouble {
200212 switch (@typeInfo(c_longdouble).float.bits) {
201 64 => return exp(x),
202 80 => return __expx(x),
203 128 => return expq(x),
204 else => @compileError("unreachable"),
213 64 => return exp_f64(x),
214 80 => return exp_f80(x),
215 128 => return exp_f128(x),
216 else => comptime unreachable,
205217 }
206218}
207219
208220test "expf() special" {
209 try expectEqual(expf(0.0), 1.0);
210 try expectEqual(expf(-0.0), 1.0);
211 try expectEqual(expf(1.0), math.e);
212 try expectEqual(expf(math.ln2), 2.0);
213 try expectEqual(expf(math.inf(f32)), math.inf(f32));
214 try expect(math.isPositiveZero(expf(-math.inf(f32))));
215 try expect(math.isNan(expf(math.nan(f32))));
216 try expect(math.isNan(expf(math.snan(f32))));
221 try expectEqual(exp_f32(0.0), 1.0);
222 try expectEqual(exp_f32(-0.0), 1.0);
223 try expectEqual(exp_f32(1.0), math.e);
224 try expectEqual(exp_f32(math.ln2), 2.0);
225 try expectEqual(exp_f32(math.inf(f32)), math.inf(f32));
226 try expect(math.isPositiveZero(exp_f32(-math.inf(f32))));
227 try expect(math.isNan(exp_f32(math.nan(f32))));
228 try expect(math.isNan(exp_f32(math.snan(f32))));
217229}
218230
219231test "expf() sanity" {
220 try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12);
221 try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6);
222 try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
223 try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10);
224 try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13);
225 try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0);
226 try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
227 try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0);
228 try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1);
229 try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1);
230 try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8);
231 try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20);
232 try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25);
233 try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20);
234 try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8);
235 try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2);
236 try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16);
237 try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24);
238 try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
239 try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28);
232 try expectEqual(exp_f32(-0x1.0223a0p+3), 0x1.490320p-12);
233 try expectEqual(exp_f32(0x1.161868p+2), 0x1.34712ap+6);
234 try expectEqual(exp_f32(-0x1.0c34b4p+3), 0x1.e06b1ap-13);
235 try expectEqual(exp_f32(-0x1.a206f0p+2), 0x1.7dd484p-10);
236 try expectEqual(exp_f32(0x1.288bbcp+3), 0x1.4abc80p+13);
237 try expectEqual(exp_f32(0x1.52efd0p-1), 0x1.f04a9cp+0);
238 try expectEqual(exp_f32(-0x1.a05cc8p-2), 0x1.54f1e0p-1);
239 try expectEqual(exp_f32(0x1.1f9efap-1), 0x1.c0f628p+0);
240 try expectEqual(exp_f32(0x1.8c5db0p-1), 0x1.1599b2p+1);
241 try expectEqual(exp_f32(-0x1.5b86eap-1), 0x1.03b572p-1);
242 try expectEqual(exp_f32(-0x1.57f25cp+2), 0x1.2fbea2p-8);
243 try expectEqual(exp_f32(0x1.c7d310p+3), 0x1.76eefp+20);
244 try expectEqual(exp_f32(0x1.19be70p+4), 0x1.52d3dep+25);
245 try expectEqual(exp_f32(-0x1.ab6d70p+3), 0x1.a88adep-20);
246 try expectEqual(exp_f32(-0x1.5ac18ep+2), 0x1.22b328p-8);
247 try expectEqual(exp_f32(-0x1.925982p-1), 0x1.d2acc0p-2);
248 try expectEqual(exp_f32(0x1.7221cep+3), 0x1.9c2ceap+16);
249 try expectEqual(exp_f32(0x1.11a0d4p+4), 0x1.980ee6p+24);
250 try expectEqual(exp_f32(-0x1.ae41a2p+1), 0x1.1c28d0p-5);
251 try expectEqual(exp_f32(-0x1.329154p+4), 0x1.47ef94p-28);
240252}
241253
242254test "expf() boundary" {
243 try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite
244 try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
245 try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value
246 try expectEqual(expf(0x1p-149), 1.0); // Min positive input value
247 try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value
248 try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input
249 try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input
250 try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero
251 try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero
252 try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal
253 try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
254
255 try expectEqual(exp_f32(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite
256 try expectEqual(exp_f32(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf
257 try expectEqual(exp_f32(0x1.fffffep+127), math.inf(f32)); // Max input value
258 try expectEqual(exp_f32(0x1p-149), 1.0); // Min positive input value
259 try expectEqual(exp_f32(-0x1p-149), 1.0); // Min negative input value
260 try expectEqual(exp_f32(0x1p-126), 1.0); // First positive subnormal input
261 try expectEqual(exp_f32(-0x1p-126), 1.0); // First negative subnormal input
262 try expectEqual(exp_f32(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero
263 try expectEqual(exp_f32(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero
264 try expectEqual(exp_f32(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal
265 try expectEqual(exp_f32(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal
255266}
256267
257268test "exp() special" {
258 try expectEqual(exp(0.0), 1.0);
259 try expectEqual(exp(-0.0), 1.0);
269 try expectEqual(exp_f64(0.0), 1.0);
270 try expectEqual(exp_f64(-0.0), 1.0);
260271 // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC
261272 // try expectEqual(exp(1.0), math.e);
262 try expectEqual(exp(math.ln2), 2.0);
263 try expectEqual(exp(math.inf(f64)), math.inf(f64));
264 try expect(math.isPositiveZero(exp(-math.inf(f64))));
265 try expect(math.isNan(exp(math.nan(f64))));
266 try expect(math.isNan(exp(math.snan(f64))));
273 try expectEqual(exp_f64(math.ln2), 2.0);
274 try expectEqual(exp_f64(math.inf(f64)), math.inf(f64));
275 try expect(math.isPositiveZero(exp_f64(-math.inf(f64))));
276 try expect(math.isNan(exp_f64(math.nan(f64))));
277 try expect(math.isNan(exp_f64(math.snan(f64))));
267278}
268279
269280test "exp() sanity" {
270 try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
271 try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
272 try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
273 try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
274 try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
275 try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
276 try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
277 try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
278 try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
279 try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
280 try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
281 try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
282 try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
283 try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
284 try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
285 try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
286 try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
287 try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
288 try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
289 try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
281 try expectEqual(exp_f64(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12);
282 try expectEqual(exp_f64(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6);
283 try expectEqual(exp_f64(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13);
284 try expectEqual(exp_f64(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10);
285 try expectEqual(exp_f64(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13);
286 try expectEqual(exp_f64(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0);
287 try expectEqual(exp_f64(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1);
288 try expectEqual(exp_f64(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0);
289 try expectEqual(exp_f64(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1);
290 try expectEqual(exp_f64(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1);
291 try expectEqual(exp_f64(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8);
292 try expectEqual(exp_f64(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20);
293 try expectEqual(exp_f64(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25);
294 try expectEqual(exp_f64(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20);
295 try expectEqual(exp_f64(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8);
296 try expectEqual(exp_f64(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2);
297 try expectEqual(exp_f64(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16);
298 try expectEqual(exp_f64(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24);
299 try expectEqual(exp_f64(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5);
300 try expectEqual(exp_f64(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28);
290301}
291302
292303test "exp() boundary" {
293 try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite
294 try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
295 try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
296 try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value
297 try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value
298 try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input
299 try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input
300 try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero
301 try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero
302 try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal
303 try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
304 try expectEqual(exp_f64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite
305 try expectEqual(exp_f64(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf
306 try expectEqual(exp_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
307 try expectEqual(exp_f64(0x1p-1074), 1.0); // Min positive input value
308 try expectEqual(exp_f64(-0x1p-1074), 1.0); // Min negative input value
309 try expectEqual(exp_f64(0x1p-1022), 1.0); // First positive subnormal input
310 try expectEqual(exp_f64(-0x1p-1022), 1.0); // First negative subnormal input
311 try expectEqual(exp_f64(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero
312 try expectEqual(exp_f64(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero
313 try expectEqual(exp_f64(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal
314 try expectEqual(exp_f64(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal
304315}
lib/compiler_rt/exp2.zig+85-73
......@@ -19,19 +19,22 @@ comptime {
1919 symbol(&exp2f, "exp2f");
2020 symbol(&exp2, "exp2");
2121 symbol(&__exp2x, "__exp2x");
22 if (compiler_rt.want_ppc_abi) {
23 symbol(&exp2q, "exp2f128");
24 }
25 symbol(&exp2q, "exp2q");
22 symbol(&exp2q, "exp2f128");
2623 symbol(&exp2l, "exp2l");
2724}
2825
29pub fn __exp2h(x: f16) callconv(.c) f16 {
26fn __exp2h(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
27 return compiler_rt.f16.toAbi(exp2_f16(compiler_rt.f16.fromAbi(x)));
28}
29pub fn exp2_f16(x: f16) f16 {
3030 // TODO: more efficient implementation
31 return @floatCast(exp2f(x));
31 return @floatCast(exp2_f32(x));
3232}
3333
34pub fn exp2f(x: f32) callconv(.c) f32 {
34fn exp2f(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
35 return compiler_rt.f32.toAbi(exp2_f32(compiler_rt.f32.fromAbi(x)));
36}
37pub fn exp2_f32(x: f32) f32 {
3538 const tblsiz: u32 = @intCast(exp2ft.len);
3639 const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz));
3740 const P1: f32 = 0x1.62e430p-1;
......@@ -88,7 +91,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 {
8891 return @floatCast(r * uk);
8992}
9093
91pub fn exp2(x: f64) callconv(.c) f64 {
94fn exp2(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
95 return compiler_rt.f64.toAbi(exp2_f64(compiler_rt.f64.fromAbi(x)));
96}
97pub fn exp2_f64(x: f64) f64 {
9298 const tblsiz: u32 = @intCast(exp2dt.len / 2);
9399 const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz));
94100 const P1: f64 = 0x1.62e42fefa39efp-1;
......@@ -156,19 +162,25 @@ pub fn exp2(x: f64) callconv(.c) f64 {
156162 return math.scalbn(r, ik);
157163}
158164
159pub fn __exp2x(x: f80) callconv(.c) f80 {
165fn __exp2x(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
166 return compiler_rt.f80.toAbi(exp2_f80(compiler_rt.f80.fromAbi(x)));
167}
168pub fn exp2_f80(x: f80) f80 {
160169 // TODO: more efficient implementation
161 return @floatCast(exp2q(x));
170 return @floatCast(exp2_f128(x));
162171}
163172
164pub const exp2q = @import("exp_f128.zig").exp2;
173fn exp2q(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
174 return compiler_rt.f128.toAbi(exp2_f128(compiler_rt.f128.fromAbi(x)));
175}
176pub const exp2_f128 = @import("exp_f128.zig").exp2;
165177
166178pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble {
167179 switch (@typeInfo(c_longdouble).float.bits) {
168 64 => return exp2(x),
169 80 => return __exp2x(x),
170 128 => return exp2q(x),
171 else => @compileError("unreachable"),
180 64 => return exp2_f64(x),
181 80 => return exp2_f80(x),
182 128 => return exp2_f128(x),
183 else => comptime unreachable,
172184 }
173185}
174186
......@@ -452,77 +464,77 @@ const exp2dt = [_]f64{
452464};
453465
454466test "exp2f() special" {
455 try expectEqual(exp2f(0.0), 1.0);
456 try expectEqual(exp2f(-0.0), 1.0);
457 try expectEqual(exp2f(1.0), 2.0);
458 try expectEqual(exp2f(-1.0), 0.5);
459 try expectEqual(exp2f(math.inf(f32)), math.inf(f32));
460 try expect(math.isPositiveZero(exp2f(-math.inf(f32))));
461 try expect(math.isNan(exp2f(math.nan(f32))));
462 try expect(math.isNan(exp2f(math.snan(f32))));
467 try expectEqual(exp2_f32(0.0), 1.0);
468 try expectEqual(exp2_f32(-0.0), 1.0);
469 try expectEqual(exp2_f32(1.0), 2.0);
470 try expectEqual(exp2_f32(-1.0), 0.5);
471 try expectEqual(exp2_f32(math.inf(f32)), math.inf(f32));
472 try expect(math.isPositiveZero(exp2_f32(-math.inf(f32))));
473 try expect(math.isNan(exp2_f32(math.nan(f32))));
474 try expect(math.isNan(exp2_f32(math.snan(f32))));
463475}
464476
465477test "exp2f() sanity" {
466 try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9);
467 try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4);
468 try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9);
469 try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7);
470 try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9);
471 try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0);
472 try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1);
473 try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0);
474 try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0);
475 try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1);
478 try expectEqual(exp2_f32(-0x1.0223a0p+3), 0x1.e8d134p-9);
479 try expectEqual(exp2_f32(0x1.161868p+2), 0x1.453672p+4);
480 try expectEqual(exp2_f32(-0x1.0c34b4p+3), 0x1.890ca0p-9);
481 try expectEqual(exp2_f32(-0x1.a206f0p+2), 0x1.622d4ep-7);
482 try expectEqual(exp2_f32(0x1.288bbcp+3), 0x1.340ecep+9);
483 try expectEqual(exp2_f32(0x1.52efd0p-1), 0x1.950eeep+0);
484 try expectEqual(exp2_f32(-0x1.a05cc8p-2), 0x1.824056p-1);
485 try expectEqual(exp2_f32(0x1.1f9efap-1), 0x1.79dfa2p+0);
486 try expectEqual(exp2_f32(0x1.8c5db0p-1), 0x1.b5ceacp+0);
487 try expectEqual(exp2_f32(-0x1.5b86eap-1), 0x1.3fd8bap-1);
476488}
477489
478490test "exp2f() boundary" {
479 try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
480 try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result
481 try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
482 try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
483 try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
484 try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
485 try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value
486 try expectEqual(exp2f(0x1p-149), 1); // Min positive input value
487 try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value
488 try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input
489 try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input
491 try expectEqual(exp2_f32(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite
492 try expectEqual(exp2_f32(0x1p+7), math.inf(f32)); // The first value that gives infinite result
493 try expectEqual(exp2_f32(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero
494 try expectEqual(exp2_f32(-0x1.2cp+7), 0); // The first value at which the result flushes to zero
495 try expectEqual(exp2_f32(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal
496 try expectEqual(exp2_f32(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal
497 try expectEqual(exp2_f32(0x1.fffffep+127), math.inf(f32)); // Max input value
498 try expectEqual(exp2_f32(0x1p-149), 1); // Min positive input value
499 try expectEqual(exp2_f32(-0x1p-149), 1); // Min negative input value
500 try expectEqual(exp2_f32(0x1p-126), 1); // First positive subnormal input
501 try expectEqual(exp2_f32(-0x1p-126), 1); // First negative subnormal input
490502}
491503
492504test "exp2() special" {
493 try expectEqual(exp2(0.0), 1.0);
494 try expectEqual(exp2(-0.0), 1.0);
495 try expectEqual(exp2(1.0), 2.0);
496 try expectEqual(exp2(-1.0), 0.5);
497 try expectEqual(exp2(math.inf(f64)), math.inf(f64));
498 try expect(math.isPositiveZero(exp2(-math.inf(f64))));
499 try expect(math.isNan(exp2(math.nan(f64))));
500 try expect(math.isNan(exp2(math.snan(f64))));
505 try expectEqual(exp2_f64(0.0), 1.0);
506 try expectEqual(exp2_f64(-0.0), 1.0);
507 try expectEqual(exp2_f64(1.0), 2.0);
508 try expectEqual(exp2_f64(-1.0), 0.5);
509 try expectEqual(exp2_f64(math.inf(f64)), math.inf(f64));
510 try expect(math.isPositiveZero(exp2_f64(-math.inf(f64))));
511 try expect(math.isNan(exp2_f64(math.nan(f64))));
512 try expect(math.isNan(exp2_f64(math.snan(f64))));
501513}
502514
503515test "exp2() sanity" {
504 try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
505 try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
506 try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
507 try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
508 try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
509 try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
510 try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
511 try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
512 try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
513 try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
516 try expectEqual(exp2_f64(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9);
517 try expectEqual(exp2_f64(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4);
518 try expectEqual(exp2_f64(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9);
519 try expectEqual(exp2_f64(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7);
520 try expectEqual(exp2_f64(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9);
521 try expectEqual(exp2_f64(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0);
522 try expectEqual(exp2_f64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1);
523 try expectEqual(exp2_f64(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0);
524 try expectEqual(exp2_f64(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0);
525 try expectEqual(exp2_f64(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1);
514526}
515527
516528test "exp2() boundary" {
517 try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
518 try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result
519 try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
520 try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
521 try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
522 try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
523 try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
524 try expectEqual(exp2(0x1p-1074), 1); // Min positive input value
525 try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value
526 try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input
527 try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input
529 try expectEqual(exp2_f64(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite
530 try expectEqual(exp2_f64(0x1p+10), math.inf(f64)); // The first value that gives infinite result
531 try expectEqual(exp2_f64(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero
532 try expectEqual(exp2_f64(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero
533 try expectEqual(exp2_f64(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal
534 try expectEqual(exp2_f64(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal
535 try expectEqual(exp2_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value
536 try expectEqual(exp2_f64(0x1p-1074), 1); // Min positive input value
537 try expectEqual(exp2_f64(-0x1p-1074), 1); // Min negative input value
538 try expectEqual(exp2_f64(0x1p-1022), 1); // First positive subnormal input
539 try expectEqual(exp2_f64(-0x1p-1022), 1); // First negative subnormal input
528540}
lib/compiler_rt/exp_f128.zig+2-2
......@@ -26,7 +26,7 @@ const exp_f128 = @This();
2626const std = @import("std");
2727const math = std.math;
2828
29pub fn exp(x: f128) callconv(.c) f128 {
29pub fn exp(x: f128) f128 {
3030 if (!math.isFinite(x)) {
3131 if (math.isNan(x)) {
3232 if (math.isSignalNan(x)) math.raiseInvalid();
......@@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 {
9191}
9292
9393/// Computes 2^x
94pub fn exp2(x: f128) callconv(.c) f128 {
94pub fn exp2(x: f128) f128 {
9595 if (!math.isFinite(x)) {
9696 if (math.isNan(x)) {
9797 if (math.isSignalNan(x)) math.raiseInvalid();
lib/compiler_rt/extenddftf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const extendf = @import("./extendf.zig").extendf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__extenddftf2, "__extenddfkf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_dtoq, "_Qp_dtoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__extenddftf2, "_Q_dtoq");
12 }
13 symbol(&__extenddftf2, "__extenddftf2");
14}
15
16pub fn __extenddftf2(a: f64) callconv(.c) f128 {
17 return extendf(f128, f64, @as(u64, @bitCast(a)));
18}
19
20fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void {
21 c.* = extendf(f128, f64, @as(u64, @bitCast(a)));
22}
lib/compiler_rt/extenddfxf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extend_f80 = @import("./extendf.zig").extend_f80;
4
5comptime {
6 symbol(&__extenddfxf2, "__extenddfxf2");
7}
8
9pub fn __extenddfxf2(a: f64) callconv(.c) f80 {
10 return extend_f80(f64, @as(u64, @bitCast(a)));
11}
lib/compiler_rt/extendf.zig+174-7
......@@ -1,10 +1,175 @@
11const std = @import("std");
22
3pub inline fn extendf(
4 comptime dst_t: type,
5 comptime src_t: type,
6 a: @Int(.unsigned, @typeInfo(src_t).float.bits),
7) dst_t {
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 if (compiler_rt.gnu_f16_abi) {
9 symbol(&__aeabi_h2f, "__gnu_h2f_ieee");
10 } else {
11 symbol(&__aeabi_h2f, "__aeabi_h2f");
12 }
13 } else if (compiler_rt.gnu_f16_abi) {
14 symbol(&__extendhfsf2, "__gnu_h2f_ieee");
15 }
16 symbol(&__extendhfsf2, "__extendhfsf2");
17 symbol(&__extendhfdf2, "__extendhfdf2");
18 symbol(&__extendhfxf2, "__extendhfxf2");
19 if (compiler_rt.want_ppc_abi) {
20 symbol(&__extendhftf2, "__extendhfkf2");
21 } else {
22 symbol(&__extendhftf2, "__extendhftf2");
23 }
24
25 if (compiler_rt.want_aeabi) {
26 symbol(&__aeabi_f2d, "__aeabi_f2d");
27 } else {
28 symbol(&__extendsfdf2, "__extendsfdf2");
29 }
30 symbol(&__extendsfxf2, "__extendsfxf2");
31 if (compiler_rt.want_ppc_abi) {
32 symbol(&__extendsftf2, "__extendsfkf2");
33 } else if (compiler_rt.want_sparc64_abi) {
34 symbol(&_Qp_stoq, "_Qp_stoq");
35 } else if (compiler_rt.want_sparc32_abi) {
36 symbol(&__extendsftf2, "_Q_stoq");
37 } else {
38 symbol(&__extendsftf2, "__extendsftf2");
39 }
40
41 symbol(&__extenddfxf2, "__extenddfxf2");
42 if (compiler_rt.want_ppc_abi) {
43 symbol(&__extenddftf2, "__extenddfkf2");
44 } else if (compiler_rt.want_sparc64_abi) {
45 symbol(&_Qp_dtoq, "_Qp_dtoq");
46 } else if (compiler_rt.want_sparc32_abi) {
47 symbol(&__extenddftf2, "_Q_dtoq");
48 } else {
49 symbol(&__extenddftf2, "__extenddftf2");
50 }
51
52 if (compiler_rt.want_ppc_abi) {
53 symbol(&__extendxftf2, "__extendxfkf2");
54 } else {
55 symbol(&__extendxftf2, "__extendxftf2");
56 }
57}
58
59fn __extendhfsf2(a: compiler_rt.f16Conv(f32).Abi) callconv(.c) compiler_rt.f32.Abi {
60 return compiler_rt.f32.toAbi(f32_floatCast_f16(compiler_rt.f16Conv(f32).fromAbi(a)));
61}
62fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) u32 {
63 return @bitCast(f32_floatCast_f16(@bitCast(a)));
64}
65pub fn f32_floatCast_f16(a: f16) f32 {
66 return extendf(f32, f16, a);
67}
68
69fn __extendhfdf2(a: compiler_rt.f16Conv(f64).Abi) callconv(.c) compiler_rt.f64.Abi {
70 return compiler_rt.f64.toAbi(f64_floatCast_f16(compiler_rt.f16Conv(f64).fromAbi(a)));
71}
72pub fn f64_floatCast_f16(a: f16) f64 {
73 return extendf(f64, f16, a);
74}
75
76fn __extendhfxf2(a: compiler_rt.f16Conv(f80).Abi) callconv(.c) compiler_rt.f80.Abi {
77 return compiler_rt.f80.toAbi(f80_floatCast_f16(compiler_rt.f16Conv(f80).fromAbi(a)));
78}
79pub fn f80_floatCast_f16(a: f16) f80 {
80 return extend_f80(f16, a);
81}
82
83fn __extendhftf2(a: compiler_rt.f16Conv(f128).Abi) callconv(.c) compiler_rt.f128.Abi {
84 return compiler_rt.f128.toAbi(f128_floatCast_f16(compiler_rt.f16Conv(f128).fromAbi(a)));
85}
86pub fn f128_floatCast_f16(a: f16) f128 {
87 return extendf(f128, f16, a);
88}
89
90fn __extendsfdf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f64.Abi {
91 return compiler_rt.f64.toAbi(f64_floatCast_f32(compiler_rt.f32.fromAbi(a)));
92}
93fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 {
94 return f64_floatCast_f32(a);
95}
96pub fn f64_floatCast_f32(a: f32) f64 {
97 return extendf(f64, f32, a);
98}
99
100fn __extendsfxf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f80.Abi {
101 return compiler_rt.f80.toAbi(f80_floatCast_f32(compiler_rt.f32.fromAbi(a)));
102}
103pub fn f80_floatCast_f32(a: f32) f80 {
104 return extend_f80(f32, a);
105}
106
107pub fn __extendsftf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f128.Abi {
108 return compiler_rt.f128.toAbi(f128_floatCast_f32(compiler_rt.f32.fromAbi(a)));
109}
110fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void {
111 c.* = f128_floatCast_f32(a);
112}
113pub fn f128_floatCast_f32(a: f32) f128 {
114 return extendf(f128, f32, a);
115}
116
117fn __extenddfxf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f80.Abi {
118 return compiler_rt.f80.toAbi(f80_floatCast_f64(compiler_rt.f64.fromAbi(a)));
119}
120pub fn f80_floatCast_f64(a: f64) f80 {
121 return extend_f80(f64, a);
122}
123
124fn __extenddftf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f128.Abi {
125 return compiler_rt.f128.toAbi(f128_floatCast_f64(compiler_rt.f64.fromAbi(a)));
126}
127fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void {
128 c.* = f128_floatCast_f64(a);
129}
130pub fn f128_floatCast_f64(a: f64) f128 {
131 return extendf(f128, f64, a);
132}
133
134fn __extendxftf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f128.Abi {
135 return compiler_rt.f128.toAbi(f128_floatCast_f80(compiler_rt.f80.fromAbi(a)));
136}
137pub fn f128_floatCast_f80(a: f80) f128 {
138 const src_int_bit: u64 = 0x8000000000000000;
139 const src_sig_mask = ~src_int_bit;
140 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
141 const dst_sig_bits = std.math.floatMantissaBits(f128);
142
143 const dst_bits = @bitSizeOf(f128);
144
145 // Break a into a sign and representation of the absolute value
146 var a_rep: std.math.F80 = .fromFloat(a);
147 const sign = a_rep.exp & 0x8000;
148 a_rep.exp &= 0x7FFF;
149 var abs_result: u128 = undefined;
150
151 if (a_rep.exp == 0 and a_rep.fraction == 0) {
152 // zero
153 abs_result = 0;
154 } else if (a_rep.exp == 0x7FFF) {
155 // a is nan or infinite
156 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
157 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
158 } else if (a_rep.fraction & src_int_bit != 0) {
159 // a is a normal value
160 abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits);
161 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
162 } else {
163 // a is denormal
164 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
165 }
166
167 // Apply the signbit to (dst_t)abs(a).
168 const result: u128 = abs_result | @as(u128, sign) << (dst_bits - 16);
169 return @bitCast(result);
170}
171
172inline fn extendf(comptime dst_t: type, comptime src_t: type, f: src_t) dst_t {
8173 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
9174 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
10175 const srcSigBits = std.math.floatMantissaBits(src_t);
......@@ -31,6 +196,7 @@ pub inline fn extendf(
31196
32197 const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;
33198
199 const a: src_rep_t = @bitCast(f);
34200 // Break a into a sign and representation of the absolute value
35201 const aRep: src_rep_t = @bitCast(a);
36202 const aAbs: src_rep_t = aRep & srcAbsMask;
......@@ -66,11 +232,11 @@ pub inline fn extendf(
66232 }
67233
68234 // Apply the signbit to (dst_t)abs(a).
69 const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
235 const result: dst_rep_t = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
70236 return @bitCast(result);
71237}
72238
73pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80 {
239inline fn extend_f80(comptime src_t: type, f: src_t) f80 {
74240 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
75241 const src_sig_bits = std.math.floatMantissaBits(src_t);
76242 const dst_int_bit = 0x8000000000000000;
......@@ -92,6 +258,7 @@ pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_
92258
93259 var dst: std.math.F80 = undefined;
94260
261 const a: src_rep_t = @bitCast(f);
95262 // Break a into a sign and representation of the absolute value
96263 const a_abs = a & src_abs_mask;
97264 const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0;
lib/compiler_rt/extendf_test.zig+94-95
......@@ -1,31 +1,37 @@
11const builtin = @import("builtin");
2
32const std = @import("std");
4const math = std.math;
3const testing = std.testing;
4
5const impl = @import("extendf.zig");
6
7const f32_floatCast_f16 = impl.f32_floatCast_f16;
8const f64_floatCast_f16 = impl.f64_floatCast_f16;
9const f80_floatCast_f16 = impl.f80_floatCast_f16;
10const f128_floatCast_f16 = impl.f128_floatCast_f16;
11
12const f64_floatCast_f32 = impl.f64_floatCast_f32;
13const f80_floatCast_f32 = impl.f80_floatCast_f32;
14const f128_floatCast_f32 = impl.f128_floatCast_f32;
515
6const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2;
7const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2;
8const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2;
9const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2;
10const __extenddfxf2 = @import("extenddfxf2.zig").__extenddfxf2;
11const F16T = @import("../compiler_rt.zig").F16T;
16const f80_floatCast_f64 = impl.f80_floatCast_f64;
17const f128_floatCast_f64 = impl.f128_floatCast_f64;
1218
13fn test__extenddfxf2(a: f64, expected: u80) !void {
14 const x = __extenddfxf2(a);
19const f128_floatCast_f80 = impl.f128_floatCast_f80;
20
21fn test_f80_floatCast_f64(a: f64, expected: u80) !void {
22 const x = f80_floatCast_f64(a);
1523
1624 const rep: u80 = @bitCast(x);
1725 if (rep == expected)
1826 return;
19
2027 // test other possible NaN representation(signal NaN)
21 if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x))
28 if (std.math.isNan(@as(f80, @bitCast(expected))) and std.math.isNan(x))
2229 return;
23
24 @panic("__extenddfxf2 test failure");
30 return error.TestFailure;
2531}
2632
27fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
28 const x = __extenddftf2(a);
33fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void {
34 const x = f128_floatCast_f64(a);
2935
3036 const rep: u128 = @bitCast(x);
3137 const hi: u64 = @intCast(rep >> 64);
......@@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
3339
3440 if (hi == expected_hi and lo == expected_lo)
3541 return;
36
3742 // test other possible NaN representation(signal NaN)
3843 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
3944 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
......@@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
4247 return;
4348 }
4449 }
45
46 @panic("__extenddftf2 test failure");
50 return error.TestFailure;
4751}
4852
49fn test__extendhfsf2(a: u16, expected: u32) !void {
50 const x = __extendhfsf2(@as(F16T(f32), @bitCast(a)));
53fn test_f32_floatCast_f16(a: u16, expected: u32) !void {
54 const x = f32_floatCast_f16(@bitCast(a));
5155 const rep: u32 = @bitCast(x);
5256
5357 if (rep == expected) {
......@@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void {
5862 return;
5963 }
6064 }
61
6265 return error.TestFailure;
6366}
6467
65fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
66 const x = __extendsftf2(a);
68fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void {
69 const x = f128_floatCast_f32(a);
6770
6871 const rep: u128 = @bitCast(x);
6972 const hi: u64 = @intCast(rep >> 64);
......@@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
7174
7275 if (hi == expected_hi and lo == expected_lo)
7376 return;
74
7577 // test other possible NaN representation(signal NaN)
7678 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
7779 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
......@@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
8082 return;
8183 }
8284 }
83
8485 return error.TestFailure;
8586}
8687
87test "extenddfxf2" {
88test f80_floatCast_f64 {
8889 // qNaN
89 try test__extenddfxf2(makeQNaN64(), 0x7fffc000000000000000);
90 try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000);
9091
9192 // NaN
92 try test__extenddfxf2(makeNaN64(0x7100000000000), 0x7fffe080000000000000);
93 try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000);
9394 // This is bad?
9495
9596 // inf
96 try test__extenddfxf2(makeInf64(), 0x7fff8000000000000000);
97 try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000);
9798
9899 // zero
99 try test__extenddfxf2(0.0, 0x0);
100 try test_f80_floatCast_f64(0.0, 0x0);
100101
101 try test__extenddfxf2(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000);
102 try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000);
102103
103 try test__extenddfxf2(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000);
104 try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000);
104105
105 try test__extenddfxf2(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000);
106 try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000);
106107
107 try test__extenddfxf2(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000);
108 try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000);
108109
109110 // subnormal
110 try test__extenddfxf2(0x1.8000000000001p-1022, 0x3c01c000000000000800);
111 try test__extenddfxf2(0x1.8000000000002p-1023, 0x3c00c000000000001000);
111 try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800);
112 try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000);
112113}
113114
114test "extenddftf2" {
115 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
116
115test f128_floatCast_f64 {
117116 // qNaN
118 try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0);
117 try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0);
119118
120119 // NaN
121 try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);
120 try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);
122121
123122 // inf
124 try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0);
123 try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0);
125124
126125 // zero
127 try test__extenddftf2(0.0, 0x0, 0x0);
126 try test_f128_floatCast_f64(0.0, 0x0, 0x0);
128127
129 try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000);
128 try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000);
130129
131 try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000);
130 try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000);
132131
133 try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000);
132 try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000);
134133
135 try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000);
134 try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000);
136135
137136 // subnormal
138 try test__extenddftf2(0x1.8p-1022, 0x3c01800000000000, 0x0);
139 try test__extenddftf2(0x1.8p-1023, 0x3c00800000000000, 0x0);
137 try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0);
138 try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0);
140139}
141140
142test "extendhfsf2" {
143 try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN
144 try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN
141test f32_floatCast_f16 {
142 try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN
143 try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN
145144 // On x86 the NaN becomes quiet because the return is pushed on the x87
146145 // stack due to ABI requirements
147146 if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows)
148 try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
147 try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN
149148
150 try test__extendhfsf2(0, 0); // 0
151 try test__extendhfsf2(0x8000, 0x80000000); // -0
149 try test_f32_floatCast_f16(0, 0); // 0
150 try test_f32_floatCast_f16(0x8000, 0x80000000); // -0
152151
153 try test__extendhfsf2(0x7c00, 0x7f800000); // inf
154 try test__extendhfsf2(0xfc00, 0xff800000); // -inf
152 try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf
153 try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf
155154
156 try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24
157 try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24
155 try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24
156 try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24
158157
159 try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24
160 try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24
158 try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24
159 try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24
161160
162 try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14
163 try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14
161 try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14
162 try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14
164163
165 try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504
166 try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504
164 try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504
165 try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504
167166
168 try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10
169 try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10
167 try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10
168 try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10
170169
171 try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3
172 try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3
170 try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3
171 try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3
173172}
174173
175test "extendsftf2" {
174test f128_floatCast_f32 {
176175 // qNaN
177 try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0);
176 try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0);
178177 // NaN
179 try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0);
178 try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0);
180179 // inf
181 try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0);
180 try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0);
182181 // zero
183 try test__extendsftf2(0.0, 0x0, 0x0);
184 try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0);
185 try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);
186 try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0);
187 try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);
182 try test_f128_floatCast_f32(0.0, 0x0, 0x0);
183 try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0);
184 try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);
185 try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0);
186 try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);
188187}
189188
190189fn makeQNaN64() f64 {
......@@ -211,8 +210,8 @@ fn makeInf32() f32 {
211210 return @bitCast(@as(u32, 0x7f800000));
212211}
213212
214fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
215 const x = __extendhftf2(@as(F16T(f128), @bitCast(a)));
213fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void {
214 const x = f128_floatCast_f16(@bitCast(a));
216215
217216 const rep: u128 = @bitCast(x);
218217 const hi: u64 = @intCast(rep >> 64);
......@@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
233232 return error.TestFailure;
234233}
235234
236test "extendhftf2" {
235test f128_floatCast_f16 {
237236 // qNaN
238 try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0);
237 try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0);
239238 // NaN
240 try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0);
239 try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0);
241240 // inf
242 try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0);
243 try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0);
241 try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0);
242 try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0);
244243 // zero
245 try test__extendhftf2(0x0000, 0x0000000000000000, 0x0);
246 try test__extendhftf2(0x8000, 0x8000000000000000, 0x0);
244 try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0);
245 try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0);
247246 // denormal
248 try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0);
249 try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0);
250 try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0);
247 try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0);
248 try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0);
249 try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0);
251250
252251 // pi
253 try test__extendhftf2(0x4248, 0x4000920000000000, 0x0);
254 try test__extendhftf2(0xc248, 0xc000920000000000, 0x0);
252 try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0);
253 try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0);
255254
256 try test__extendhftf2(0x508c, 0x4004230000000000, 0x0);
257 try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0);
255 try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0);
256 try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0);
258257}
lib/compiler_rt/extendhfdf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 symbol(&__extendhfdf2, "__extendhfdf2");
7}
8
9pub fn __extendhfdf2(a: compiler_rt.F16T(f64)) callconv(.c) f64 {
10 return extendf(f64, f16, @as(u16, @bitCast(a)));
11}
lib/compiler_rt/extendhfsf2.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const extendf = @import("./extendf.zig").extendf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.gnu_f16_abi) {
7 symbol(&__gnu_h2f_ieee, "__gnu_h2f_ieee");
8 } else if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_h2f, "__aeabi_h2f");
10 }
11 symbol(&__extendhfsf2, "__extendhfsf2");
12}
13
14pub fn __extendhfsf2(a: compiler_rt.F16T(f32)) callconv(.c) f32 {
15 return extendf(f32, f16, @as(u16, @bitCast(a)));
16}
17
18fn __gnu_h2f_ieee(a: compiler_rt.F16T(f32)) callconv(.c) f32 {
19 return extendf(f32, f16, @as(u16, @bitCast(a)));
20}
21
22fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) f32 {
23 return extendf(f32, f16, @as(u16, @bitCast(a)));
24}
lib/compiler_rt/extendhftf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 symbol(&__extendhftf2, "__extendhftf2");
7}
8
9pub fn __extendhftf2(a: compiler_rt.F16T(f128)) callconv(.c) f128 {
10 return extendf(f128, f16, @as(u16, @bitCast(a)));
11}
lib/compiler_rt/extendhfxf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extend_f80 = @import("./extendf.zig").extend_f80;
4
5comptime {
6 symbol(&__extendhfxf2, "__extendhfxf2");
7}
8
9fn __extendhfxf2(a: compiler_rt.F16T(f80)) callconv(.c) f80 {
10 return extend_f80(f16, @as(u16, @bitCast(a)));
11}
lib/compiler_rt/extendsfdf2.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_f2d, "__aeabi_f2d");
8 } else {
9 symbol(&__extendsfdf2, "__extendsfdf2");
10 }
11}
12
13fn __extendsfdf2(a: f32) callconv(.c) f64 {
14 return extendf(f64, f32, @as(u32, @bitCast(a)));
15}
16
17fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return extendf(f64, f32, @as(u32, @bitCast(a)));
19}
lib/compiler_rt/extendsftf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const extendf = @import("./extendf.zig").extendf;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__extendsftf2, "__extendsfkf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_stoq, "_Qp_stoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__extendsftf2, "_Q_stoq");
12 }
13 symbol(&__extendsftf2, "__extendsftf2");
14}
15
16pub fn __extendsftf2(a: f32) callconv(.c) f128 {
17 return extendf(f128, f32, @as(u32, @bitCast(a)));
18}
19
20fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void {
21 c.* = extendf(f128, f32, @as(u32, @bitCast(a)));
22}
lib/compiler_rt/extendsfxf2.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const extend_f80 = @import("./extendf.zig").extend_f80;
3
4comptime {
5 symbol(&__extendsfxf2, "__extendsfxf2");
6}
7
8fn __extendsfxf2(a: f32) callconv(.c) f80 {
9 return extend_f80(f32, @as(u32, @bitCast(a)));
10}
lib/compiler_rt/extendxftf2.zig deleted-42
......@@ -1,42 +0,0 @@
1const std = @import("std");
2
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__extendxftf2, "__extendxftf2");
7}
8
9fn __extendxftf2(a: f80) callconv(.c) f128 {
10 const src_int_bit: u64 = 0x8000000000000000;
11 const src_sig_mask = ~src_int_bit;
12 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
13 const dst_sig_bits = std.math.floatMantissaBits(f128);
14
15 const dst_bits = @bitSizeOf(f128);
16
17 // Break a into a sign and representation of the absolute value
18 var a_rep = std.math.F80.fromFloat(a);
19 const sign = a_rep.exp & 0x8000;
20 a_rep.exp &= 0x7FFF;
21 var abs_result: u128 = undefined;
22
23 if (a_rep.exp == 0 and a_rep.fraction == 0) {
24 // zero
25 abs_result = 0;
26 } else if (a_rep.exp == 0x7FFF) {
27 // a is nan or infinite
28 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
29 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
30 } else if (a_rep.fraction & src_int_bit != 0) {
31 // a is a normal value
32 abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits);
33 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
34 } else {
35 // a is denormal
36 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
37 }
38
39 // Apply the signbit to (dst_t)abs(a).
40 const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16);
41 return @bitCast(result);
42}
lib/compiler_rt/fabs.zig+25-13
......@@ -9,39 +9,51 @@ comptime {
99 symbol(&fabsf, "fabsf");
1010 symbol(&fabs, "fabs");
1111 symbol(&__fabsx, "__fabsx");
12 if (compiler_rt.want_ppc_abi) {
13 symbol(&fabsq, "fabsf128");
14 }
15 symbol(&fabsq, "fabsq");
12 symbol(&fabsq, "fabsf128");
1613 symbol(&fabsl, "fabsl");
1714}
1815
19pub fn __fabsh(a: f16) callconv(.c) f16 {
16fn __fabsh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
17 return compiler_rt.f16.toAbi(fabs_f16(compiler_rt.f16.fromAbi(a)));
18}
19pub fn fabs_f16(a: f16) f16 {
2020 return generic_fabs(a);
2121}
2222
23pub fn fabsf(a: f32) callconv(.c) f32 {
23fn fabsf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
24 return compiler_rt.f32.toAbi(fabs_f32(compiler_rt.f32.fromAbi(a)));
25}
26pub fn fabs_f32(a: f32) f32 {
2427 return generic_fabs(a);
2528}
2629
27pub fn fabs(a: f64) callconv(.c) f64 {
30fn fabs(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
31 return compiler_rt.f64.toAbi(fabs_f64(compiler_rt.f64.fromAbi(a)));
32}
33pub fn fabs_f64(a: f64) f64 {
2834 return generic_fabs(a);
2935}
3036
31pub fn __fabsx(a: f80) callconv(.c) f80 {
37fn __fabsx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
38 return compiler_rt.f80.toAbi(fabs_f80(compiler_rt.f80.fromAbi(a)));
39}
40pub fn fabs_f80(a: f80) f80 {
3241 return generic_fabs(a);
3342}
3443
35pub fn fabsq(a: f128) callconv(.c) f128 {
44fn fabsq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
45 return compiler_rt.f128.toAbi(fabs_f128(compiler_rt.f128.fromAbi(a)));
46}
47pub fn fabs_f128(a: f128) f128 {
3648 return generic_fabs(a);
3749}
3850
3951pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble {
4052 switch (@typeInfo(c_longdouble).float.bits) {
41 64 => return fabs(x),
42 80 => return __fabsx(x),
43 128 => return fabsq(x),
44 else => @compileError("unreachable"),
53 64 => return fabs_f64(x),
54 80 => return fabs_f80(x),
55 128 => return fabs_f128(x),
56 else => comptime unreachable,
4557 }
4658}
4759
lib/compiler_rt/fixdfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_d2lz, "__aeabi_d2lz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixdfdi, "__dtoi64");
12 }
13 symbol(&__fixdfdi, "__fixdfdi");
14 }
15}
16
17pub fn __fixdfdi(a: f64) callconv(.c) i64 {
18 return intFromFloat(i64, a);
19}
20
21fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 {
22 return intFromFloat(i64, a);
23}
lib/compiler_rt/fixdfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixdfei, "__fixdfei");
9}
10
11pub fn __fixdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixdfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2iz, "__aeabi_d2iz");
8 } else {
9 symbol(&__fixdfsi, "__fixdfsi");
10 }
11}
12
13pub fn __fixdfsi(a: f64) callconv(.c) i32 {
14 return intFromFloat(i32, a);
15}
16
17fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
18 return intFromFloat(i32, a);
19}
lib/compiler_rt/fixdfti.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__fixdfti, "__fixdfti");
7}
8
9pub fn __fixdfti(a: f64) callconv(.c) i128 {
10 return intFromFloat(i128, a);
11}
lib/compiler_rt/fixhfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixhfei, "__fixhfei");
9}
10
11pub fn __fixhfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixint_test.zig deleted-149
......@@ -1,149 +0,0 @@
1const std = @import("std");
2const math = std.math;
3const testing = std.testing;
4
5const fixint = @import("fixint.zig").fixint;
6
7fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) !void {
8 const x = fixint(fp_t, fixint_t, a);
9 try testing.expect(x == expected);
10}
11
12test "fixint.i1" {
13 try test__fixint(f32, i1, -math.inf(f32), -1);
14 try test__fixint(f32, i1, -math.floatMax(f32), -1);
15 try test__fixint(f32, i1, -2.0, -1);
16 try test__fixint(f32, i1, -1.1, -1);
17 try test__fixint(f32, i1, -1.0, -1);
18 try test__fixint(f32, i1, -0.9, 0);
19 try test__fixint(f32, i1, -0.1, 0);
20 try test__fixint(f32, i1, -math.floatMin(f32), 0);
21 try test__fixint(f32, i1, -0.0, 0);
22 try test__fixint(f32, i1, 0.0, 0);
23 try test__fixint(f32, i1, math.floatMin(f32), 0);
24 try test__fixint(f32, i1, 0.1, 0);
25 try test__fixint(f32, i1, 0.9, 0);
26 try test__fixint(f32, i1, 1.0, 0);
27 try test__fixint(f32, i1, 2.0, 0);
28 try test__fixint(f32, i1, math.floatMax(f32), 0);
29 try test__fixint(f32, i1, math.inf(f32), 0);
30}
31
32test "fixint.i2" {
33 try test__fixint(f32, i2, -math.inf(f32), -2);
34 try test__fixint(f32, i2, -math.floatMax(f32), -2);
35 try test__fixint(f32, i2, -2.0, -2);
36 try test__fixint(f32, i2, -1.9, -1);
37 try test__fixint(f32, i2, -1.1, -1);
38 try test__fixint(f32, i2, -1.0, -1);
39 try test__fixint(f32, i2, -0.9, 0);
40 try test__fixint(f32, i2, -0.1, 0);
41 try test__fixint(f32, i2, -math.floatMin(f32), 0);
42 try test__fixint(f32, i2, -0.0, 0);
43 try test__fixint(f32, i2, 0.0, 0);
44 try test__fixint(f32, i2, math.floatMin(f32), 0);
45 try test__fixint(f32, i2, 0.1, 0);
46 try test__fixint(f32, i2, 0.9, 0);
47 try test__fixint(f32, i2, 1.0, 1);
48 try test__fixint(f32, i2, 2.0, 1);
49 try test__fixint(f32, i2, math.floatMax(f32), 1);
50 try test__fixint(f32, i2, math.inf(f32), 1);
51}
52
53test "fixint.i3" {
54 try test__fixint(f32, i3, -math.inf(f32), -4);
55 try test__fixint(f32, i3, -math.floatMax(f32), -4);
56 try test__fixint(f32, i3, -4.0, -4);
57 try test__fixint(f32, i3, -3.0, -3);
58 try test__fixint(f32, i3, -2.0, -2);
59 try test__fixint(f32, i3, -1.9, -1);
60 try test__fixint(f32, i3, -1.1, -1);
61 try test__fixint(f32, i3, -1.0, -1);
62 try test__fixint(f32, i3, -0.9, 0);
63 try test__fixint(f32, i3, -0.1, 0);
64 try test__fixint(f32, i3, -math.floatMin(f32), 0);
65 try test__fixint(f32, i3, -0.0, 0);
66 try test__fixint(f32, i3, 0.0, 0);
67 try test__fixint(f32, i3, math.floatMin(f32), 0);
68 try test__fixint(f32, i3, 0.1, 0);
69 try test__fixint(f32, i3, 0.9, 0);
70 try test__fixint(f32, i3, 1.0, 1);
71 try test__fixint(f32, i3, 2.0, 2);
72 try test__fixint(f32, i3, 3.0, 3);
73 try test__fixint(f32, i3, 4.0, 3);
74 try test__fixint(f32, i3, math.floatMax(f32), 3);
75 try test__fixint(f32, i3, math.inf(f32), 3);
76}
77
78test "fixint.i32" {
79 try test__fixint(f64, i32, -math.inf(f64), math.minInt(i32));
80 try test__fixint(f64, i32, -math.floatMax(f64), math.minInt(i32));
81 try test__fixint(f64, i32, @as(f64, math.minInt(i32)), math.minInt(i32));
82 try test__fixint(f64, i32, @as(f64, math.minInt(i32)) + 1, math.minInt(i32) + 1);
83 try test__fixint(f64, i32, -2.0, -2);
84 try test__fixint(f64, i32, -1.9, -1);
85 try test__fixint(f64, i32, -1.1, -1);
86 try test__fixint(f64, i32, -1.0, -1);
87 try test__fixint(f64, i32, -0.9, 0);
88 try test__fixint(f64, i32, -0.1, 0);
89 try test__fixint(f64, i32, -@as(f64, math.floatMin(f32)), 0);
90 try test__fixint(f64, i32, -0.0, 0);
91 try test__fixint(f64, i32, 0.0, 0);
92 try test__fixint(f64, i32, @as(f64, math.floatMin(f32)), 0);
93 try test__fixint(f64, i32, 0.1, 0);
94 try test__fixint(f64, i32, 0.9, 0);
95 try test__fixint(f64, i32, 1.0, 1);
96 try test__fixint(f64, i32, @as(f64, math.maxInt(i32)) - 1, math.maxInt(i32) - 1);
97 try test__fixint(f64, i32, @as(f64, math.maxInt(i32)), math.maxInt(i32));
98 try test__fixint(f64, i32, math.floatMax(f64), math.maxInt(i32));
99 try test__fixint(f64, i32, math.inf(f64), math.maxInt(i32));
100}
101
102test "fixint.i64" {
103 try test__fixint(f64, i64, -math.inf(f64), math.minInt(i64));
104 try test__fixint(f64, i64, -math.floatMax(f64), math.minInt(i64));
105 try test__fixint(f64, i64, @as(f64, math.minInt(i64)), math.minInt(i64));
106 try test__fixint(f64, i64, @as(f64, math.minInt(i64)) + 1, math.minInt(i64));
107 try test__fixint(f64, i64, @as(f64, math.minInt(i64) / 2), math.minInt(i64) / 2);
108 try test__fixint(f64, i64, -2.0, -2);
109 try test__fixint(f64, i64, -1.9, -1);
110 try test__fixint(f64, i64, -1.1, -1);
111 try test__fixint(f64, i64, -1.0, -1);
112 try test__fixint(f64, i64, -0.9, 0);
113 try test__fixint(f64, i64, -0.1, 0);
114 try test__fixint(f64, i64, -@as(f64, math.floatMin(f32)), 0);
115 try test__fixint(f64, i64, -0.0, 0);
116 try test__fixint(f64, i64, 0.0, 0);
117 try test__fixint(f64, i64, @as(f64, math.floatMin(f32)), 0);
118 try test__fixint(f64, i64, 0.1, 0);
119 try test__fixint(f64, i64, 0.9, 0);
120 try test__fixint(f64, i64, 1.0, 1);
121 try test__fixint(f64, i64, @as(f64, math.maxInt(i64)) - 1, math.maxInt(i64));
122 try test__fixint(f64, i64, @as(f64, math.maxInt(i64)), math.maxInt(i64));
123 try test__fixint(f64, i64, math.floatMax(f64), math.maxInt(i64));
124 try test__fixint(f64, i64, math.inf(f64), math.maxInt(i64));
125}
126
127test "fixint.i128" {
128 try test__fixint(f64, i128, -math.inf(f64), math.minInt(i128));
129 try test__fixint(f64, i128, -math.floatMax(f64), math.minInt(i128));
130 try test__fixint(f64, i128, @as(f64, math.minInt(i128)), math.minInt(i128));
131 try test__fixint(f64, i128, @as(f64, math.minInt(i128)) + 1, math.minInt(i128));
132 try test__fixint(f64, i128, -2.0, -2);
133 try test__fixint(f64, i128, -1.9, -1);
134 try test__fixint(f64, i128, -1.1, -1);
135 try test__fixint(f64, i128, -1.0, -1);
136 try test__fixint(f64, i128, -0.9, 0);
137 try test__fixint(f64, i128, -0.1, 0);
138 try test__fixint(f64, i128, -@as(f64, math.floatMin(f32)), 0);
139 try test__fixint(f64, i128, -0.0, 0);
140 try test__fixint(f64, i128, 0.0, 0);
141 try test__fixint(f64, i128, @as(f64, math.floatMin(f32)), 0);
142 try test__fixint(f64, i128, 0.1, 0);
143 try test__fixint(f64, i128, 0.9, 0);
144 try test__fixint(f64, i128, 1.0, 1);
145 try test__fixint(f64, i128, @as(f64, math.maxInt(i128)) - 1, math.maxInt(i128));
146 try test__fixint(f64, i128, @as(f64, math.maxInt(i128)), math.maxInt(i128));
147 try test__fixint(f64, i128, math.floatMax(f64), math.maxInt(i128));
148 try test__fixint(f64, i128, math.inf(f64), math.maxInt(i128));
149}
lib/compiler_rt/fixsfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4const symbol = @import("../compiler_rt.zig").symbol;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_f2lz, "__aeabi_f2lz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixsfdi, "__stoi64");
12 }
13 symbol(&__fixsfdi, "__fixsfdi");
14 }
15}
16
17pub fn __fixsfdi(a: f32) callconv(.c) i64 {
18 return intFromFloat(i64, a);
19}
20
21fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 {
22 return intFromFloat(i64, a);
23}
lib/compiler_rt/fixsfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixsfei, "__fixsfei");
9}
10
11pub fn __fixsfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixsfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_f2iz, "__aeabi_f2iz");
8 } else {
9 symbol(&__fixsfsi, "__fixsfsi");
10 }
11}
12
13pub fn __fixsfsi(a: f32) callconv(.c) i32 {
14 return intFromFloat(i32, a);
15}
16
17fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
18 return intFromFloat(i32, a);
19}
lib/compiler_rt/fixsfti.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 symbol(&__fixsfti, "__fixsfti");
8}
9
10pub fn __fixsfti(a: f32) callconv(.c) i128 {
11 return intFromFloat(i128, a);
12}
lib/compiler_rt/fixtfdi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixtfdi, "__fixkfdi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtox, "_Qp_qtox");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixtfdi, "_Q_qtoll");
12 }
13 symbol(&__fixtfdi, "__fixtfdi");
14}
15
16pub fn __fixtfdi(a: f128) callconv(.c) i64 {
17 return intFromFloat(i64, a);
18}
19
20fn _Qp_qtox(a: *const f128) callconv(.c) i64 {
21 return intFromFloat(i64, a.*);
22}
lib/compiler_rt/fixtfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixtfei, "__fixtfei");
9}
10
11pub fn __fixtfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixtfsi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixtfsi, "__fixkfsi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtoi, "_Qp_qtoi");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixtfsi, "_Q_qtoi");
12 }
13 symbol(&__fixtfsi, "__fixtfsi");
14}
15
16pub fn __fixtfsi(a: f128) callconv(.c) i32 {
17 return intFromFloat(i32, a);
18}
19
20fn _Qp_qtoi(a: *const f128) callconv(.c) i32 {
21 return intFromFloat(i32, a.*);
22}
lib/compiler_rt/fixtfti.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi)
7 symbol(&__fixtfti, "__fixkfti");
8 symbol(&__fixtfti, "__fixtfti");
9}
10
11pub fn __fixtfti(a: f128) callconv(.c) i128 {
12 return intFromFloat(i128, a);
13}
lib/compiler_rt/fixunsdfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_d2ulz, "__aeabi_d2ulz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixunsdfdi, "__dtou64");
12 }
13 symbol(&__fixunsdfdi, "__fixunsdfdi");
14 }
15}
16
17pub fn __fixunsdfdi(a: f64) callconv(.c) u64 {
18 return intFromFloat(u64, a);
19}
20
21fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 {
22 return intFromFloat(u64, a);
23}
lib/compiler_rt/fixunsdfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunsdfei, "__fixunsdfei");
10}
11
12pub fn __fixunsdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunsdfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2uiz, "__aeabi_d2uiz");
8 } else {
9 symbol(&__fixunsdfsi, "__fixunsdfsi");
10 }
11}
12
13pub fn __fixunsdfsi(a: f64) callconv(.c) u32 {
14 return intFromFloat(u32, a);
15}
16
17fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 {
18 return intFromFloat(u32, a);
19}
lib/compiler_rt/fixunsdfti.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixunsdfti, "__fixunsdfti");
7}
8
9pub fn __fixunsdfti(a: f64) callconv(.c) u128 {
10 return intFromFloat(u128, a);
11}
lib/compiler_rt/fixunshfdi.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3
4comptime {
5 symbol(&__fixunshfdi, "__fixunshfdi");
6}
7
8fn __fixunshfdi(a: f16) callconv(.c) u64 {
9 return intFromFloat(u64, a);
10}
lib/compiler_rt/fixunshfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunshfei, "__fixunshfei");
10}
11
12pub fn __fixunshfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunshfsi.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixunshfsi, "__fixunshfsi");
7}
8
9fn __fixunshfsi(a: f16) callconv(.c) u32 {
10 return intFromFloat(u32, a);
11}
lib/compiler_rt/fixunshfti.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__fixunshfti, "__fixunshfti");
7}
8
9pub fn __fixunshfti(a: f16) callconv(.c) u128 {
10 return intFromFloat(u128, a);
11}
lib/compiler_rt/fixunssfdi.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_f2ulz, "__aeabi_f2ulz");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__fixunssfdi, "__stou64");
12 }
13 symbol(&__fixunssfdi, "__fixunssfdi");
14 }
15}
16
17pub fn __fixunssfdi(a: f32) callconv(.c) u64 {
18 return intFromFloat(u64, a);
19}
20
21fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 {
22 return intFromFloat(u64, a);
23}
lib/compiler_rt/fixunssfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunssfei, "__fixunssfei");
10}
11
12pub fn __fixunssfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunssfsi.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_f2uiz, "__aeabi_f2uiz");
8 } else {
9 symbol(&__fixunssfsi, "__fixunssfsi");
10 }
11}
12
13pub fn __fixunssfsi(a: f32) callconv(.c) u32 {
14 return intFromFloat(u32, a);
15}
16
17fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 {
18 return intFromFloat(u32, a);
19}
lib/compiler_rt/fixunssfti.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4const symbol = @import("../compiler_rt.zig").symbol;
5
6comptime {
7 symbol(&__fixunssfti, "__fixunssfti");
8}
9
10pub fn __fixunssfti(a: f32) callconv(.c) u128 {
11 return intFromFloat(u128, a);
12}
lib/compiler_rt/fixunstfdi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixunstfdi, "__fixunskfdi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtoux, "_Qp_qtoux");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixunstfdi, "_Q_qtoull");
12 }
13 symbol(&__fixunstfdi, "__fixunstfdi");
14}
15
16pub fn __fixunstfdi(a: f128) callconv(.c) u64 {
17 return intFromFloat(u64, a);
18}
19
20fn _Qp_qtoux(a: *const f128) callconv(.c) u64 {
21 return intFromFloat(u64, a.*);
22}
lib/compiler_rt/fixunstfei.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
7
8comptime {
9 symbol(&__fixunstfei, "__fixunstfei");
10}
11
12pub fn __fixunstfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
15}
lib/compiler_rt/fixunstfsi.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__fixunstfsi, "__fixunskfsi");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtoui, "_Qp_qtoui");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__fixunstfsi, "_Q_qtou");
12 }
13 symbol(&__fixunstfsi, "__fixunstfsi");
14}
15
16pub fn __fixunstfsi(a: f128) callconv(.c) u32 {
17 return intFromFloat(u32, a);
18}
19
20fn _Qp_qtoui(a: *const f128) callconv(.c) u32 {
21 return intFromFloat(u32, a.*);
22}
lib/compiler_rt/fixunstfti.zig deleted-14
......@@ -1,14 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 if (compiler_rt.want_ppc_abi)
8 symbol(&__fixunstfti, "__fixunskfti");
9 symbol(&__fixunstfti, "__fixunstfti");
10}
11
12pub fn __fixunstfti(a: f128) callconv(.c) u128 {
13 return intFromFloat(u128, a);
14}
lib/compiler_rt/fixunsxfdi.zig deleted-10
......@@ -1,10 +0,0 @@
1const intFromFloat = @import("./int_from_float.zig").intFromFloat;
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 symbol(&__fixunsxfdi, "__fixunsxfdi");
6}
7
8fn __fixunsxfdi(a: f80) callconv(.c) u64 {
9 return intFromFloat(u64, a);
10}
lib/compiler_rt/fixunsxfei.zig deleted-13
......@@ -1,13 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const symbol = @import("../compiler_rt.zig").symbol;
4const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
5
6comptime {
7 symbol(&__fixunsxfei, "__fixunsxfei");
8}
9
10pub fn __fixunsxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void {
11 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
12 return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a);
13}
lib/compiler_rt/fixunsxfsi.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixunsxfsi, "__fixunsxfsi");
7}
8
9fn __fixunsxfsi(a: f80) callconv(.c) u32 {
10 return intFromFloat(u32, a);
11}
lib/compiler_rt/fixunsxfti.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const intFromFloat = @import("./int_from_float.zig").intFromFloat;
5
6comptime {
7 symbol(&__fixunsxfti, "__fixunsxfti");
8}
9
10pub fn __fixunsxfti(a: f80) callconv(.c) u128 {
11 return intFromFloat(u128, a);
12}
lib/compiler_rt/fixxfdi.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const intFromFloat = @import("./int_from_float.zig").intFromFloat;
3
4comptime {
5 symbol(&__fixxfdi, "__fixxfdi");
6}
7
8fn __fixxfdi(a: f80) callconv(.c) i64 {
9 return intFromFloat(i64, a);
10}
lib/compiler_rt/fixxfei.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat;
6
7comptime {
8 symbol(&__fixxfei, "__fixxfei");
9}
10
11pub fn __fixxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a);
14}
lib/compiler_rt/fixxfsi.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const intFromFloat = @import("./int_from_float.zig").intFromFloat;
4
5comptime {
6 symbol(&__fixxfsi, "__fixxfsi");
7}
8
9fn __fixxfsi(a: f80) callconv(.c) i32 {
10 return intFromFloat(i32, a);
11}
lib/compiler_rt/float_from_int.zig+472-4
......@@ -1,7 +1,475 @@
1const builtin = @import("builtin");
12const std = @import("std");
23const math = std.math;
34
4pub fn floatFromInt(comptime T: type, x: anytype) T {
5const compiler_rt = @import("../compiler_rt.zig");
6const symbol = compiler_rt.symbol;
7
8comptime {
9 symbol(&__floatsihf, "__floatsihf");
10 symbol(&__floatdihf, "__floatdihf");
11 symbol(&__floattihf, "__floattihf");
12 symbol(&__floateihf, "__floateihf");
13
14 if (compiler_rt.want_aeabi) {
15 symbol(&__aeabi_i2f, "__aeabi_i2f");
16 symbol(&__aeabi_l2f, "__aeabi_l2f");
17 } else {
18 symbol(&__floatsisf, "__floatsisf");
19 symbol(&__floatdisf, "__floatdisf");
20 if (compiler_rt.want_windows_arm_abi) symbol(&__floatdisf, "__i64tos");
21 }
22 symbol(&__floattisf, "__floattisf");
23 symbol(&__floateisf, "__floateisf");
24
25 if (compiler_rt.want_aeabi) {
26 symbol(&__aeabi_i2d, "__aeabi_i2d");
27 symbol(&__aeabi_l2d, "__aeabi_l2d");
28 } else {
29 symbol(&__floatsidf, "__floatsidf");
30 symbol(&__floatdidf, "__floatdidf");
31 if (compiler_rt.want_windows_arm_abi) symbol(&__floatdidf, "__i64tod");
32 }
33 symbol(&__floattidf, "__floattidf");
34 symbol(&__floateidf, "__floateidf");
35
36 symbol(&__floatsixf, "__floatsixf");
37 symbol(&__floatdixf, "__floatdixf");
38 symbol(&__floattixf, "__floattixf");
39 symbol(&__floateixf, "__floateixf");
40
41 if (compiler_rt.want_ppc_abi) {
42 symbol(&__floatsitf, "__floatsikf");
43 symbol(&__floatditf, "__floatdikf");
44 } else if (compiler_rt.want_sparc64_abi) {
45 symbol(&_Qp_itoq, "_Qp_itoq");
46 symbol(&_Qp_xtoq, "_Qp_xtoq");
47 } else if (compiler_rt.want_sparc32_abi) {
48 symbol(&__floatsitf, "_Q_itoq");
49 symbol(&__floatditf, "_Q_lltoq");
50 } else {
51 symbol(&__floatsitf, "__floatsitf");
52 symbol(&__floatditf, "__floatditf");
53 }
54 if (compiler_rt.want_ppc_abi) {
55 symbol(&__floattitf, "__floattikf");
56 symbol(&__floateitf, "__floateikf");
57 } else {
58 if (builtin.cpu.arch == .x86) {
59 symbol(&__floattitf_x86, "__floattitf");
60 } else {
61 symbol(&__floattitf, "__floattitf");
62 }
63 symbol(&__floateitf, "__floateitf");
64 }
65}
66
67fn __floatsihf(a: i32) callconv(.c) compiler_rt.f16.Abi {
68 return compiler_rt.f16.toAbi(f16_floatFromInt_i32(a));
69}
70pub fn f16_floatFromInt_i32(a: i32) f16 {
71 return floatFromInt(f16, a);
72}
73
74fn __floatdihf(a: i64) callconv(.c) compiler_rt.f16.Abi {
75 return compiler_rt.f16.toAbi(f16_floatFromInt_i64(a));
76}
77pub fn f16_floatFromInt_i64(a: i64) f16 {
78 return floatFromInt(f16, a);
79}
80
81fn __floattihf(a: i128) callconv(.c) compiler_rt.f16.Abi {
82 return compiler_rt.f16.toAbi(f16_floatFromInt_i128(a));
83}
84pub fn f16_floatFromInt_i128(a: i128) f16 {
85 return floatFromInt(f16, a);
86}
87
88fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi {
89 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
90 return compiler_rt.f16.toAbi(f16_floatFromInt_signed(a[0..byte_size]));
91}
92pub fn f16_floatFromInt_signed(a: []const u8) f16 {
93 return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a)));
94}
95
96fn __floatsisf(a: i32) callconv(.c) compiler_rt.f32.Abi {
97 return compiler_rt.f32.toAbi(f32_floatFromInt_i32(a));
98}
99fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 {
100 return f32_floatFromInt_i32(a);
101}
102pub fn f32_floatFromInt_i32(a: i32) f32 {
103 return floatFromInt(f32, a);
104}
105
106fn __floatdisf(a: i64) callconv(.c) compiler_rt.f32.Abi {
107 return compiler_rt.f32.toAbi(f32_floatFromInt_i64(a));
108}
109fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 {
110 return f32_floatFromInt_i64(a);
111}
112pub fn f32_floatFromInt_i64(a: i64) f32 {
113 return floatFromInt(f32, a);
114}
115
116fn __floattisf(a: i128) callconv(.c) compiler_rt.f32.Abi {
117 return compiler_rt.f32.toAbi(f32_floatFromInt_i128(a));
118}
119pub fn f32_floatFromInt_i128(a: i128) f32 {
120 return floatFromInt(f32, a);
121}
122
123fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi {
124 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
125 return compiler_rt.f32.toAbi(f32_floatFromInt_signed(a[0..byte_size]));
126}
127pub fn f32_floatFromInt_signed(a: []const u8) f32 {
128 return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a)));
129}
130
131fn __floatsidf(a: i32) callconv(.c) compiler_rt.f64.Abi {
132 return compiler_rt.f64.toAbi(f64_floatFromInt_i32(a));
133}
134fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 {
135 return f64_floatFromInt_i32(a);
136}
137pub fn f64_floatFromInt_i32(a: i32) f64 {
138 return floatFromInt(f64, a);
139}
140
141fn __floatdidf(a: i64) callconv(.c) compiler_rt.f64.Abi {
142 return compiler_rt.f64.toAbi(f64_floatFromInt_i64(a));
143}
144fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 {
145 return f64_floatFromInt_i64(a);
146}
147pub fn f64_floatFromInt_i64(a: i64) f64 {
148 return floatFromInt(f64, a);
149}
150
151fn __floattidf(a: i128) callconv(.c) compiler_rt.f64.Abi {
152 return compiler_rt.f64.toAbi(f64_floatFromInt_i128(a));
153}
154pub fn f64_floatFromInt_i128(a: i128) f64 {
155 return floatFromInt(f64, a);
156}
157
158fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi {
159 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
160 return compiler_rt.f64.toAbi(f64_floatFromInt_signed(a[0..byte_size]));
161}
162pub fn f64_floatFromInt_signed(a: []const u8) f64 {
163 return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a)));
164}
165
166fn __floatsixf(a: i32) callconv(.c) compiler_rt.f80.Abi {
167 return compiler_rt.f80.toAbi(f80_floatFromInt_i32(a));
168}
169pub fn f80_floatFromInt_i32(a: i32) f80 {
170 return floatFromInt(f80, a);
171}
172
173fn __floatdixf(a: i64) callconv(.c) compiler_rt.f80.Abi {
174 return compiler_rt.f80.toAbi(f80_floatFromInt_i64(a));
175}
176pub fn f80_floatFromInt_i64(a: i64) f80 {
177 return floatFromInt(f80, a);
178}
179
180fn __floattixf(a: i128) callconv(.c) compiler_rt.f80.Abi {
181 return compiler_rt.f80.toAbi(f80_floatFromInt_i128(a));
182}
183pub fn f80_floatFromInt_i128(a: i128) f80 {
184 return floatFromInt(f80, a);
185}
186
187fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi {
188 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
189 return compiler_rt.f80.toAbi(f80_floatFromInt_signed(a[0..byte_size]));
190}
191pub fn f80_floatFromInt_signed(a: []const u8) f80 {
192 return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a)));
193}
194
195fn __floatsitf(a: i32) callconv(.c) compiler_rt.f128.Abi {
196 return compiler_rt.f128.toAbi(f128_floatFromInt_i32(a));
197}
198fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void {
199 c.* = f128_floatFromInt_i32(a);
200}
201pub fn f128_floatFromInt_i32(a: i32) f128 {
202 return floatFromInt(f128, a);
203}
204
205fn __floatditf(a: i64) callconv(.c) compiler_rt.f128.Abi {
206 return compiler_rt.f128.toAbi(f128_floatFromInt_i64(a));
207}
208fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void {
209 c.* = f128_floatFromInt_i64(a);
210}
211pub fn f128_floatFromInt_i64(a: i64) f128 {
212 return floatFromInt(f128, a);
213}
214
215fn __floattitf(a: i128) callconv(.c) compiler_rt.f128.Abi {
216 return compiler_rt.f128.toAbi(f128_floatFromInt_i128(a));
217}
218fn __floattitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi {
219 return compiler_rt.f128.toAbi(f128_floatFromInt_i128(@bitCast(a)));
220}
221pub fn f128_floatFromInt_i128(a: i128) f128 {
222 return floatFromInt(f128, a);
223}
224
225fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi {
226 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
227 return compiler_rt.f128.toAbi(f128_floatFromInt_signed(a[0..byte_size]));
228}
229pub fn f128_floatFromInt_signed(a: []const u8) f128 {
230 return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a)));
231}
232
233comptime {
234 symbol(&__floatunsihf, "__floatunsihf");
235 symbol(&__floatundihf, "__floatundihf");
236 symbol(&__floatuntihf, "__floatuntihf");
237 symbol(&__floatuneihf, "__floatuneihf");
238
239 if (compiler_rt.want_aeabi) {
240 symbol(&__aeabi_ui2f, "__aeabi_ui2f");
241 symbol(&__aeabi_ul2f, "__aeabi_ul2f");
242 } else {
243 symbol(&__floatunsisf, "__floatunsisf");
244 symbol(&__floatundisf, "__floatundisf");
245 if (compiler_rt.want_windows_arm_abi) symbol(&__floatundisf, "__u64tos");
246 }
247 symbol(&__floatuntisf, "__floatuntisf");
248 symbol(&__floatuneisf, "__floatuneisf");
249
250 if (compiler_rt.want_aeabi) {
251 symbol(&__aeabi_ui2d, "__aeabi_ui2d");
252 } else {
253 symbol(&__floatunsidf, "__floatunsidf");
254 }
255 if (compiler_rt.want_aeabi) {
256 symbol(&__aeabi_ul2d, "__aeabi_ul2d");
257 } else {
258 if (compiler_rt.want_windows_arm_abi) {
259 symbol(&__floatundidf, "__u64tod");
260 }
261 symbol(&__floatundidf, "__floatundidf");
262 }
263 symbol(&__floatuntidf, "__floatuntidf");
264 symbol(&__floatuneidf, "__floatuneidf");
265
266 symbol(&__floatunsixf, "__floatunsixf");
267 symbol(&__floatundixf, "__floatundixf");
268 symbol(&__floatuntixf, "__floatuntixf");
269 symbol(&__floatuneixf, "__floatuneixf");
270
271 if (compiler_rt.want_ppc_abi) {
272 symbol(&__floatunsitf, "__floatunsikf");
273 symbol(&__floatunditf, "__floatundikf");
274 } else if (compiler_rt.want_sparc64_abi) {
275 symbol(&_Qp_uitoq, "_Qp_uitoq");
276 symbol(&_Qp_uxtoq, "_Qp_uxtoq");
277 } else if (compiler_rt.want_sparc32_abi) {
278 symbol(&__floatunsitf, "_Q_utoq");
279 symbol(&__floatunditf, "_Q_ulltoq");
280 } else {
281 symbol(&__floatunsitf, "__floatunsitf");
282 symbol(&__floatunditf, "__floatunditf");
283 }
284 if (compiler_rt.want_ppc_abi) {
285 symbol(&__floatuntitf, "__floatuntikf");
286 symbol(&__floatuneitf, "__floatuneikf");
287 } else {
288 if (builtin.cpu.arch == .x86) {
289 symbol(&__floatuntitf_x86, "__floatuntitf");
290 } else if (builtin.cpu.arch == .x86_64 and
291 (builtin.os.tag == .windows or builtin.os.tag == .uefi))
292 {
293 symbol(&__floatuntitf_x86_64_windows, "__floatuntitf");
294 } else {
295 symbol(&__floatuntitf, "__floatuntitf");
296 }
297 symbol(&__floatuneitf, "__floatuneitf");
298 }
299}
300
301fn __floatunsihf(a: u32) callconv(.c) compiler_rt.f16.Abi {
302 return compiler_rt.f16.toAbi(f16_floatFromInt_u32(a));
303}
304pub fn f16_floatFromInt_u32(a: u32) f16 {
305 return floatFromInt(f16, a);
306}
307
308fn __floatundihf(a: u64) callconv(.c) compiler_rt.f16.Abi {
309 return compiler_rt.f16.toAbi(f16_floatFromInt_u64(a));
310}
311pub fn f16_floatFromInt_u64(a: u64) f16 {
312 return floatFromInt(f16, a);
313}
314
315fn __floatuntihf(a: u128) callconv(.c) compiler_rt.f16.Abi {
316 return compiler_rt.f16.toAbi(f16_floatFromInt_u128(a));
317}
318pub fn f16_floatFromInt_u128(a: u128) f16 {
319 return floatFromInt(f16, a);
320}
321
322fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi {
323 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
324 return compiler_rt.f16.toAbi(f16_floatFromInt_unsigned(a[0..byte_size]));
325}
326pub fn f16_floatFromInt_unsigned(a: []const u8) f16 {
327 return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a)));
328}
329
330fn __floatunsisf(a: u32) callconv(.c) compiler_rt.f32.Abi {
331 return compiler_rt.f32.toAbi(f32_floatFromInt_u32(a));
332}
333fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 {
334 return f32_floatFromInt_u32(a);
335}
336pub fn f32_floatFromInt_u32(a: u32) f32 {
337 return floatFromInt(f32, a);
338}
339
340fn __floatundisf(a: u64) callconv(.c) compiler_rt.f32.Abi {
341 return compiler_rt.f32.toAbi(f32_floatFromInt_u64(a));
342}
343fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 {
344 return f32_floatFromInt_u64(a);
345}
346pub fn f32_floatFromInt_u64(a: u64) f32 {
347 return floatFromInt(f32, a);
348}
349
350fn __floatuntisf(a: u128) callconv(.c) compiler_rt.f32.Abi {
351 return compiler_rt.f32.toAbi(f32_floatFromInt_u128(a));
352}
353pub fn f32_floatFromInt_u128(a: u128) f32 {
354 return floatFromInt(f32, a);
355}
356
357fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi {
358 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
359 return compiler_rt.f32.toAbi(f32_floatFromInt_unsigned(a[0..byte_size]));
360}
361pub fn f32_floatFromInt_unsigned(a: []const u8) f32 {
362 return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a)));
363}
364
365fn __floatunsidf(a: u32) callconv(.c) compiler_rt.f64.Abi {
366 return compiler_rt.f64.toAbi(f64_floatFromInt_u32(a));
367}
368fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 {
369 return f64_floatFromInt_u32(a);
370}
371pub fn f64_floatFromInt_u32(a: u32) f64 {
372 return floatFromInt(f64, a);
373}
374
375fn __floatundidf(a: u64) callconv(.c) compiler_rt.f64.Abi {
376 return compiler_rt.f64.toAbi(f64_floatFromInt_u64(a));
377}
378fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 {
379 return f64_floatFromInt_u64(a);
380}
381pub fn f64_floatFromInt_u64(a: u64) f64 {
382 return floatFromInt(f64, a);
383}
384
385fn __floatuntidf(a: u128) callconv(.c) compiler_rt.f64.Abi {
386 return compiler_rt.f64.toAbi(f64_floatFromInt_u128(a));
387}
388pub fn f64_floatFromInt_u128(a: u128) f64 {
389 return floatFromInt(f64, a);
390}
391
392fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi {
393 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
394 return compiler_rt.f64.toAbi(f64_floatFromInt_unsigned(a[0..byte_size]));
395}
396pub fn f64_floatFromInt_unsigned(a: []const u8) f64 {
397 return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a)));
398}
399
400fn __floatunsixf(a: u32) callconv(.c) compiler_rt.f80.Abi {
401 return compiler_rt.f80.toAbi(f80_floatFromInt_u32(a));
402}
403pub fn f80_floatFromInt_u32(a: u32) f80 {
404 return floatFromInt(f80, a);
405}
406
407fn __floatundixf(a: u64) callconv(.c) compiler_rt.f80.Abi {
408 return compiler_rt.f80.toAbi(f80_floatFromInt_u64(a));
409}
410pub fn f80_floatFromInt_u64(a: u64) f80 {
411 return floatFromInt(f80, a);
412}
413
414fn __floatuntixf(a: u128) callconv(.c) compiler_rt.f80.Abi {
415 return compiler_rt.f80.toAbi(f80_floatFromInt_u128(a));
416}
417pub fn f80_floatFromInt_u128(a: u128) f80 {
418 return floatFromInt(f80, a);
419}
420
421fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi {
422 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
423 return compiler_rt.f80.toAbi(f80_floatFromInt_unsigned(a[0..byte_size]));
424}
425pub fn f80_floatFromInt_unsigned(a: []const u8) f80 {
426 return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a)));
427}
428
429fn __floatunsitf(a: u32) callconv(.c) compiler_rt.f128.Abi {
430 return compiler_rt.f128.toAbi(f128_floatFromInt_u32(a));
431}
432fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void {
433 c.* = f128_floatFromInt_u32(a);
434}
435pub fn f128_floatFromInt_u32(a: u32) f128 {
436 return floatFromInt(f128, a);
437}
438
439fn __floatunditf(a: u64) callconv(.c) compiler_rt.f128.Abi {
440 return compiler_rt.f128.toAbi(f128_floatFromInt_u64(a));
441}
442fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void {
443 c.* = f128_floatFromInt_u64(a);
444}
445pub fn f128_floatFromInt_u64(a: u64) f128 {
446 return floatFromInt(f128, a);
447}
448
449fn __floatuntitf(a: u128) callconv(.c) compiler_rt.f128.Abi {
450 return compiler_rt.f128.toAbi(f128_floatFromInt_u128(a));
451}
452fn __floatuntitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi {
453 return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(a)));
454}
455fn __floatuntitf_x86_64_windows(a_lo: u64, a_hi: u64) callconv(.c) compiler_rt.f128.Abi {
456 return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(
457 packed struct { lo: u64, hi: u64 }{ .lo = a_lo, .hi = a_hi },
458 )));
459}
460pub fn f128_floatFromInt_u128(a: u128) f128 {
461 return floatFromInt(f128, a);
462}
463
464fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi {
465 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
466 return compiler_rt.f128.toAbi(f128_floatFromInt_unsigned(a[0..byte_size]));
467}
468pub fn f128_floatFromInt_unsigned(a: []const u8) f128 {
469 return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a)));
470}
471
472inline fn floatFromInt(comptime T: type, x: anytype) T {
5473 if (x == 0) return 0;
6474
7475 // Various constants whose values follow from the type parameters.
......@@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
53521 return @bitCast(sign_bit | result);
54522}
55523
56const endian = @import("builtin").cpu.arch.endian();
524const endian = builtin.cpu.arch.endian();
57525inline fn limb(limbs: []const u32, index: usize) u32 {
58526 return switch (endian) {
59527 .little => limbs[index],
......@@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 {
61529 };
62530}
63531
64pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T {
532inline fn floatFromBigInt(comptime T: type, comptime signedness: std.lang.Signedness, x: []const u32) T {
65533 switch (x.len) {
66534 0 => return 0,
67535 inline 1...4 => |limbs_len| {
68 const low_to_high: [limbs_len]u32 = switch (@import("builtin").cpu.arch.endian()) {
536 const low_to_high: [limbs_len]u32 = switch (endian) {
69537 .little => x[0..limbs_len].*,
70538 .big => switch (limbs_len) {
71539 1 => .{x[0]},
lib/compiler_rt/float_from_int_test.zig+757-733
......@@ -2,571 +2,593 @@ const std = @import("std");
22const testing = std.testing;
33const math = std.math;
44
5const __floatunsihf = @import("floatunsihf.zig").__floatunsihf;
6
7// Conversion to f32
8const __floatsisf = @import("floatsisf.zig").__floatsisf;
9const __floatunsisf = @import("floatunsisf.zig").__floatunsisf;
10const __floatdisf = @import("floatdisf.zig").__floatdisf;
11const __floatundisf = @import("floatundisf.zig").__floatundisf;
12const __floattisf = @import("floattisf.zig").__floattisf;
13const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
14const __floateisf = @import("floateisf.zig").__floateisf;
15const __floatuneisf = @import("floatuneisf.zig").__floatuneisf;
16
17// Conversion to f64
18const __floatsidf = @import("floatsidf.zig").__floatsidf;
19const __floatunsidf = @import("floatunsidf.zig").__floatunsidf;
20const __floatdidf = @import("floatdidf.zig").__floatdidf;
21const __floatundidf = @import("floatundidf.zig").__floatundidf;
22const __floattidf = @import("floattidf.zig").__floattidf;
23const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;
24
25// Conversion to f128
26const __floatsitf = @import("floatsitf.zig").__floatsitf;
27const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
28const __floatditf = @import("floatditf.zig").__floatditf;
29const __floatunditf = @import("floatunditf.zig").__floatunditf;
30const __floattitf = @import("floattitf.zig").__floattitf;
31const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
32
33fn test__floatsisf(a: i32, expected: u32) !void {
34 const r = __floatsisf(a);
5const impl = @import("float_from_int.zig");
6
7const f16_floatFromInt_i32 = impl.f16_floatFromInt_i32;
8const f16_floatFromInt_u32 = impl.f16_floatFromInt_u32;
9const f16_floatFromInt_i64 = impl.f16_floatFromInt_i64;
10const f16_floatFromInt_u64 = impl.f16_floatFromInt_u64;
11const f16_floatFromInt_i128 = impl.f16_floatFromInt_i128;
12const f16_floatFromInt_u128 = impl.f16_floatFromInt_u128;
13const f16_floatFromInt_signed = impl.f16_floatFromInt_signed;
14const f16_floatFromInt_unsigned = impl.f16_floatFromInt_unsigned;
15
16const f32_floatFromInt_i32 = impl.f32_floatFromInt_i32;
17const f32_floatFromInt_u32 = impl.f32_floatFromInt_u32;
18const f32_floatFromInt_i64 = impl.f32_floatFromInt_i64;
19const f32_floatFromInt_u64 = impl.f32_floatFromInt_u64;
20const f32_floatFromInt_i128 = impl.f32_floatFromInt_i128;
21const f32_floatFromInt_u128 = impl.f32_floatFromInt_u128;
22const f32_floatFromInt_signed = impl.f32_floatFromInt_signed;
23const f32_floatFromInt_unsigned = impl.f32_floatFromInt_unsigned;
24
25const f64_floatFromInt_i32 = impl.f64_floatFromInt_i32;
26const f64_floatFromInt_u32 = impl.f64_floatFromInt_u32;
27const f64_floatFromInt_i64 = impl.f64_floatFromInt_i64;
28const f64_floatFromInt_u64 = impl.f64_floatFromInt_u64;
29const f64_floatFromInt_i128 = impl.f64_floatFromInt_i128;
30const f64_floatFromInt_u128 = impl.f64_floatFromInt_u128;
31const f64_floatFromInt_signed = impl.f64_floatFromInt_signed;
32const f64_floatFromInt_unsigned = impl.f64_floatFromInt_unsigned;
33
34const f80_floatFromInt_i32 = impl.f80_floatFromInt_i32;
35const f80_floatFromInt_u32 = impl.f80_floatFromInt_u32;
36const f80_floatFromInt_i64 = impl.f80_floatFromInt_i64;
37const f80_floatFromInt_u64 = impl.f80_floatFromInt_u64;
38const f80_floatFromInt_i128 = impl.f80_floatFromInt_i128;
39const f80_floatFromInt_u128 = impl.f80_floatFromInt_u128;
40const f80_floatFromInt_signed = impl.f80_floatFromInt_signed;
41const f80_floatFromInt_unsigned = impl.f80_floatFromInt_unsigned;
42
43const f128_floatFromInt_i32 = impl.f128_floatFromInt_i32;
44const f128_floatFromInt_u32 = impl.f128_floatFromInt_u32;
45const f128_floatFromInt_i64 = impl.f128_floatFromInt_i64;
46const f128_floatFromInt_u64 = impl.f128_floatFromInt_u64;
47const f128_floatFromInt_i128 = impl.f128_floatFromInt_i128;
48const f128_floatFromInt_u128 = impl.f128_floatFromInt_u128;
49const f128_floatFromInt_signed = impl.f128_floatFromInt_signed;
50const f128_floatFromInt_unsigned = impl.f128_floatFromInt_unsigned;
51
52fn test_f32_floatFromInt_i32(a: i32, expected: u32) !void {
53 const r = f32_floatFromInt_i32(a);
3554 try std.testing.expect(@as(u32, @bitCast(r)) == expected);
3655}
3756
38fn test_one_floatunsisf(a: u32, expected: u32) !void {
39 const r = __floatunsisf(a);
57fn test_f32_floatFromInt_u32(a: u32, expected: u32) !void {
58 const r = f32_floatFromInt_u32(a);
4059 try std.testing.expect(@as(u32, @bitCast(r)) == expected);
4160}
4261
43test "floatsisf" {
44 try test__floatsisf(0, 0x00000000);
45 try test__floatsisf(1, 0x3f800000);
46 try test__floatsisf(-1, 0xbf800000);
47 try test__floatsisf(0x7FFFFFFF, 0x4f000000);
48 try test__floatsisf(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000);
62test f32_floatFromInt_i32 {
63 try test_f32_floatFromInt_i32(0, 0x00000000);
64 try test_f32_floatFromInt_i32(1, 0x3f800000);
65 try test_f32_floatFromInt_i32(-1, 0xbf800000);
66 try test_f32_floatFromInt_i32(0x7FFFFFFF, 0x4f000000);
67 try test_f32_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000);
68
69 try testing.expect(f32_floatFromInt_i32(math.minInt(i32)) == math.minInt(i32));
4970}
5071
51test "floatunsisf" {
72test f32_floatFromInt_u32 {
5273 // Test the produced bit pattern
53 try test_one_floatunsisf(0, 0);
54 try test_one_floatunsisf(1, 0x3f800000);
55 try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000);
56 try test_one_floatunsisf(0x80000000, 0x4f000000);
57 try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000);
74 try test_f32_floatFromInt_u32(0, 0);
75 try test_f32_floatFromInt_u32(1, 0x3f800000);
76 try test_f32_floatFromInt_u32(0x7FFFFFFF, 0x4f000000);
77 try test_f32_floatFromInt_u32(0x80000000, 0x4f000000);
78 try test_f32_floatFromInt_u32(0xFFFFFFFF, 0x4f800000);
79
80 try testing.expect(f32_floatFromInt_u32(0) == 0.0);
81 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24)) == math.maxInt(u24));
82 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact
83 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even
84 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact
85 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even
86 try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact
87 try testing.expect(f32_floatFromInt_u32(math.maxInt(u32)) == math.maxInt(u32) + 1);
88}
89
90fn test_f32_floatFromInt_i64(a: i64, expected: f32) !void {
91 const x = f32_floatFromInt_i64(a);
92 try testing.expect(x == expected);
5893}
5994
60fn test__floatdisf(a: i64, expected: f32) !void {
61 const x = __floatdisf(a);
95fn test_f32_floatFromInt_u64(a: u64, expected: f32) !void {
96 const x = f32_floatFromInt_u64(a);
6297 try testing.expect(x == expected);
6398}
6499
65fn test__floatundisf(a: u64, expected: f32) !void {
66 try std.testing.expectEqual(expected, __floatundisf(a));
67}
68
69test "floatdisf" {
70 try test__floatdisf(0, 0.0);
71 try test__floatdisf(1, 1.0);
72 try test__floatdisf(2, 2.0);
73 try test__floatdisf(-1, -1.0);
74 try test__floatdisf(-2, -2.0);
75 try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
76 try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
77 try test__floatdisf(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
78 try test__floatdisf(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
79 try test__floatdisf(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63);
80 try test__floatdisf(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63);
81 try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
82 try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
83 try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
84 try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
85 try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
86 try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
87 try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
88 try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
89 try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
90 try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
91 try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
92}
93
94test "floatundisf" {
95 try test__floatundisf(0, 0.0);
96 try test__floatundisf(1, 1.0);
97 try test__floatundisf(2, 2.0);
98 try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
99 try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
100 try test__floatundisf(0x8000008000000000, 0x1p+63);
101 try test__floatundisf(0x8000010000000000, 0x1.000002p+63);
102 try test__floatundisf(0x8000000000000000, 0x1p+63);
103 try test__floatundisf(0x8000000000000001, 0x1p+63);
104 try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
105 try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
106 try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
107 try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
108 try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
109 try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
110 try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
111 try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
112 try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
113 try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
114 try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
115 try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
116 try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
117}
118
119fn test__floattisf(a: i128, expected: f32) !void {
120 const x = __floattisf(a);
100test f32_floatFromInt_i64 {
101 try test_f32_floatFromInt_i64(0, 0.0);
102 try test_f32_floatFromInt_i64(1, 1.0);
103 try test_f32_floatFromInt_i64(2, 2.0);
104 try test_f32_floatFromInt_i64(-1, -1.0);
105 try test_f32_floatFromInt_i64(-2, -2.0);
106 try test_f32_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
107 try test_f32_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
108 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
109 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
110 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63);
111 try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63);
112 try test_f32_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
113 try test_f32_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBAp+50);
114 try test_f32_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBAp+50);
115 try test_f32_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
116 try test_f32_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBCp+50);
117 try test_f32_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBAp+50);
118 try test_f32_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCBAp+50);
119 try test_f32_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCBAp+50);
120 try test_f32_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
121 try test_f32_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCBAp+50);
122 try test_f32_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB8p+50);
123}
124
125test f32_floatFromInt_u64 {
126 try test_f32_floatFromInt_u64(0, 0.0);
127 try test_f32_floatFromInt_u64(1, 1.0);
128 try test_f32_floatFromInt_u64(2, 2.0);
129 try test_f32_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
130 try test_f32_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
131 try test_f32_floatFromInt_u64(0x8000008000000000, 0x1p+63);
132 try test_f32_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63);
133 try test_f32_floatFromInt_u64(0x8000000000000000, 0x1p+63);
134 try test_f32_floatFromInt_u64(0x8000000000000001, 0x1p+63);
135 try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFE, 0x1p+64);
136 try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFF, 0x1p+64);
137 try test_f32_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
138 try test_f32_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBAp+50);
139 try test_f32_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBAp+50);
140 try test_f32_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
141 try test_f32_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBCp+50);
142 try test_f32_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBAp+50);
143 try test_f32_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCBAp+50);
144 try test_f32_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCBAp+50);
145 try test_f32_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
146 try test_f32_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCBAp+50);
147 try test_f32_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB8p+50);
148}
149
150fn test_f32_floatFromInt_i128(a: i128, expected: f32) !void {
151 const x = f32_floatFromInt_i128(a);
121152 try testing.expect(x == expected);
122153}
123154
124fn test__floatuntisf(a: u128, expected: f32) !void {
125 const x = __floatuntisf(a);
155fn test_f32_floatFromInt_u128(a: u128, expected: f32) !void {
156 const x = f32_floatFromInt_u128(a);
126157 try testing.expect(x == expected);
127158}
128159
129test "floattisf" {
130 try test__floattisf(0, 0.0);
160test f32_floatFromInt_i128 {
161 try test_f32_floatFromInt_i128(0, 0.0);
131162
132 try test__floattisf(1, 1.0);
133 try test__floattisf(2, 2.0);
134 try test__floattisf(-1, -1.0);
135 try test__floattisf(-2, -2.0);
163 try test_f32_floatFromInt_i128(1, 1.0);
164 try test_f32_floatFromInt_i128(2, 2.0);
165 try test_f32_floatFromInt_i128(-1, -1.0);
166 try test_f32_floatFromInt_i128(-2, -2.0);
136167
137 try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
138 try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
168 try test_f32_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
169 try test_f32_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
139170
140 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62);
141 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62);
171 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62);
172 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62);
142173
143 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63);
144 try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63);
174 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63);
175 try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63);
145176
146 try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
177 try test_f32_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
147178
148 try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
149 try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
150 try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
151 try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
152 try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
179 try test_f32_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBAp+50);
180 try test_f32_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBAp+50);
181 try test_f32_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
182 try test_f32_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBCp+50);
183 try test_f32_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBAp+50);
153184
154 try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
155 try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
156 try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
157 try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
158 try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
185 try test_f32_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCBAp+50);
186 try test_f32_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCBAp+50);
187 try test_f32_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
188 try test_f32_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCBAp+50);
189 try test_f32_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB8p+50);
159190
160 try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114);
191 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114);
161192
162 try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114);
163 try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114);
164 try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114);
165 try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114);
166 try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114);
193 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114);
194 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114);
195 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114);
196 try test_f32_floatFromInt_i128(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114);
197 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114);
167198
168 try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114);
169 try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114);
170 try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114);
171 try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114);
172 try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114);
199 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114);
200 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114);
201 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114);
202 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114);
203 try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114);
173204}
174205
175test "floatuntisf" {
176 try test__floatuntisf(0, 0.0);
206test f32_floatFromInt_u128 {
207 try test_f32_floatFromInt_u128(0, 0.0);
177208
178 try test__floatuntisf(1, 1.0);
179 try test__floatuntisf(2, 2.0);
180 try test__floatuntisf(20, 20.0);
209 try test_f32_floatFromInt_u128(1, 1.0);
210 try test_f32_floatFromInt_u128(2, 2.0);
211 try test_f32_floatFromInt_u128(20, 20.0);
181212
182 try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
183 try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
213 try test_f32_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
214 try test_f32_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
184215
185 try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
186 try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127);
187 try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
216 try test_f32_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
217 try test_f32_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0p+127);
218 try test_f32_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
188219
189 try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
220 try test_f32_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
190221
191 try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
222 try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
192223
193 try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
194 try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
224 try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
225 try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
195226
196 try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
227 try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
197228
198 try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
199 try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
200 try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
229 try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
230 try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
231 try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
201232
202 try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
203 try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
233 try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0x1p+64);
234 try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0x1p+64);
204235
205 try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
236 try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
206237
207 try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
208 try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
209 try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
210 try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
211 try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
238 try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBAp+50);
239 try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBAp+50);
240 try test_f32_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
241 try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBCp+50);
242 try test_f32_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBAp+50);
212243
213 try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
214 try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
215 try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
216 try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
217 try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
244 try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCBAp+50);
245 try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCBAp+50);
246 try test_f32_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
247 try test_f32_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCBAp+50);
248 try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB8p+50);
218249
219 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);
220 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);
221 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);
222 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);
223 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);
224 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);
225 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);
226 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);
227 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);
228 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);
229 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);
230 try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
250 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76);
251 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76);
252 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76);
253 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76);
254 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76);
255 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76);
256 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76);
257 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76);
258 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76);
259 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76);
260 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76);
261 try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
231262
232263 // Test overflow to infinity
233 try test__floatuntisf(math.maxInt(u128), @bitCast(math.inf(f32)));
264 try test_f32_floatFromInt_u128(math.maxInt(u128), @bitCast(math.inf(f32)));
234265}
235266
236fn test_floateisf(expected: u32, comptime T: type, a: T) !void {
267fn test_f32_floatFromInt(expected: u32, comptime T: type, a: T) !void {
237268 const int = @typeInfo(T).int;
238269 const r = switch (int.signedness) {
239 .signed => __floateisf,
240 .unsigned => __floatuneisf,
241 }(@ptrCast(&a), int.bits);
270 .signed => f32_floatFromInt_signed,
271 .unsigned => f32_floatFromInt_unsigned,
272 }(@ptrCast(&a));
242273 try testing.expect(expected == @as(u32, @bitCast(r)));
243274}
244275
245test "floateisf" {
246 try test_floateisf(0xFF000000, i256, -1 << 127);
247 try test_floateisf(0xFF000000, i256, -math.maxInt(u127));
248 try test_floateisf(0xDF012347, i256, -0x8123468100000000);
249 try test_floateisf(0xDF012347, i256, -0x8123468000000001);
250 try test_floateisf(0xDF012346, i256, -0x8123468000000000);
251 try test_floateisf(0xDF012346, i256, -0x8123458100000000);
252 try test_floateisf(0xDF012346, i256, -0x8123458000000001);
253 try test_floateisf(0xDF012346, i256, -0x8123458000000000);
254 try test_floateisf(0xDF012345, i256, -0x8123456789ABCDEF);
255 try test_floateisf(0xBF800000, i256, -1);
256 try test_floateisf(0x00000000, i256, 0);
257 try test_floateisf(0x5F012345, i256, 0x8123456789ABCDEF);
258 try test_floateisf(0x5F012346, i256, 0x8123458000000000);
259 try test_floateisf(0x5F012346, i256, 0x8123458000000001);
260 try test_floateisf(0x5F012346, i256, 0x8123458100000000);
261 try test_floateisf(0x5F012346, i256, 0x8123468000000000);
262 try test_floateisf(0x5F012347, i256, 0x8123468000000001);
263 try test_floateisf(0x5F012347, i256, 0x8123468100000000);
264 try test_floateisf(0x7F000000, i256, math.maxInt(u127));
265 try test_floateisf(0x7F000000, i256, 1 << 127);
266}
267
268test "floatuneisf" {
269 try test_floateisf(0x00000000, u256, 0);
270 try test_floateisf(0x5F012345, u256, 0x8123456789ABCDEF);
271 try test_floateisf(0x5F012346, u256, 0x8123458000000000);
272 try test_floateisf(0x5F012346, u256, 0x8123458000000001);
273 try test_floateisf(0x5F012346, u256, 0x8123458080000000);
274 try test_floateisf(0x5F012346, u256, 0x8123468000000000);
275 try test_floateisf(0x5F012347, u256, 0x8123468000000001);
276 try test_floateisf(0x5F012347, u256, 0x8123468080000000);
277 try test_floateisf(0x7F000000, u256, math.maxInt(u127));
278 try test_floateisf(0x7F000000, u256, 1 << 127);
279 try test_floateisf(0x7F800000, u256, math.maxInt(u256));
280}
281
282fn test_one_floatsidf(a: i32, expected: u64) !void {
283 const r = __floatsidf(a);
276test f32_floatFromInt_signed {
277 try test_f32_floatFromInt(0xFF000000, i256, -1 << 127);
278 try test_f32_floatFromInt(0xFF000000, i256, -math.maxInt(u127));
279 try test_f32_floatFromInt(0xDF012347, i256, -0x8123468100000000);
280 try test_f32_floatFromInt(0xDF012347, i256, -0x8123468000000001);
281 try test_f32_floatFromInt(0xDF012346, i256, -0x8123468000000000);
282 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458100000000);
283 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000001);
284 try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000000);
285 try test_f32_floatFromInt(0xDF012345, i256, -0x8123456789ABCDEF);
286 try test_f32_floatFromInt(0xBF800000, i256, -1);
287 try test_f32_floatFromInt(0x00000000, i256, 0);
288 try test_f32_floatFromInt(0x5F012345, i256, 0x8123456789ABCDEF);
289 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000000);
290 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000001);
291 try test_f32_floatFromInt(0x5F012346, i256, 0x8123458100000000);
292 try test_f32_floatFromInt(0x5F012346, i256, 0x8123468000000000);
293 try test_f32_floatFromInt(0x5F012347, i256, 0x8123468000000001);
294 try test_f32_floatFromInt(0x5F012347, i256, 0x8123468100000000);
295 try test_f32_floatFromInt(0x7F000000, i256, math.maxInt(u127));
296 try test_f32_floatFromInt(0x7F000000, i256, 1 << 127);
297}
298
299test f32_floatFromInt_unsigned {
300 try test_f32_floatFromInt(0x00000000, u256, 0);
301 try test_f32_floatFromInt(0x5F012345, u256, 0x8123456789ABCDEF);
302 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000000);
303 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000001);
304 try test_f32_floatFromInt(0x5F012346, u256, 0x8123458080000000);
305 try test_f32_floatFromInt(0x5F012346, u256, 0x8123468000000000);
306 try test_f32_floatFromInt(0x5F012347, u256, 0x8123468000000001);
307 try test_f32_floatFromInt(0x5F012347, u256, 0x8123468080000000);
308 try test_f32_floatFromInt(0x7F000000, u256, math.maxInt(u127));
309 try test_f32_floatFromInt(0x7F000000, u256, 1 << 127);
310 try test_f32_floatFromInt(0x7F800000, u256, math.maxInt(u256));
311}
312
313fn test_f64_floatFromInt_i32(a: i32, expected: u64) !void {
314 const r = f64_floatFromInt_i32(a);
284315 try std.testing.expect(@as(u64, @bitCast(r)) == expected);
285316}
286317
287fn test_one_floatunsidf(a: u32, expected: u64) !void {
288 const r = __floatunsidf(a);
318fn test_f64_floatFromInt_u32(a: u32, expected: u64) !void {
319 const r = f64_floatFromInt_u32(a);
289320 try std.testing.expect(@as(u64, @bitCast(r)) == expected);
290321}
291322
292test "floatsidf" {
293 try test_one_floatsidf(0, 0x0000000000000000);
294 try test_one_floatsidf(1, 0x3ff0000000000000);
295 try test_one_floatsidf(-1, 0xbff0000000000000);
296 try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
297 try test_one_floatsidf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000);
323test f64_floatFromInt_i32 {
324 try test_f64_floatFromInt_i32(0, 0x0000000000000000);
325 try test_f64_floatFromInt_i32(1, 0x3ff0000000000000);
326 try test_f64_floatFromInt_i32(-1, 0xbff0000000000000);
327 try test_f64_floatFromInt_i32(0x7FFFFFFF, 0x41dfffffffc00000);
328 try test_f64_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000);
298329}
299330
300test "floatunsidf" {
301 try test_one_floatunsidf(0, 0x0000000000000000);
302 try test_one_floatunsidf(1, 0x3ff0000000000000);
303 try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);
304 try test_one_floatunsidf(@intCast(0x80000000), 0x41e0000000000000);
305 try test_one_floatunsidf(@intCast(0xFFFFFFFF), 0x41efffffffe00000);
331test f64_floatFromInt_u32 {
332 try test_f64_floatFromInt_u32(0, 0x0000000000000000);
333 try test_f64_floatFromInt_u32(1, 0x3ff0000000000000);
334 try test_f64_floatFromInt_u32(0x7FFFFFFF, 0x41dfffffffc00000);
335 try test_f64_floatFromInt_u32(@intCast(0x80000000), 0x41e0000000000000);
336 try test_f64_floatFromInt_u32(@intCast(0xFFFFFFFF), 0x41efffffffe00000);
306337}
307338
308fn test__floatdidf(a: i64, expected: f64) !void {
309 const r = __floatdidf(a);
339fn test_f64_floatFromInt_i64(a: i64, expected: f64) !void {
340 const r = f64_floatFromInt_i64(a);
310341 try testing.expect(r == expected);
311342}
312343
313fn test__floatundidf(a: u64, expected: f64) !void {
314 const r = __floatundidf(a);
344fn test_f64_floatFromInt_u64(a: u64, expected: f64) !void {
345 const r = f64_floatFromInt_u64(a);
315346 try testing.expect(r == expected);
316347}
317348
318test "floatdidf" {
319 try test__floatdidf(0, 0.0);
320 try test__floatdidf(1, 1.0);
321 try test__floatdidf(2, 2.0);
322 try test__floatdidf(20, 20.0);
323 try test__floatdidf(-1, -1.0);
324 try test__floatdidf(-2, -2.0);
325 try test__floatdidf(-20, -20.0);
326 try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
327 try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
328 try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
329 try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
330 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62);
331 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62);
332 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62);
333 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62);
334 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63);
335 try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001
336 try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
337 try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
338 try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
339 try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
340 try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
341 try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
342 try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
343 try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
344 try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
345 try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
346 try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
347 try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
348 try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
349 try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
350 try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
351 try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
352 try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
353 try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
354 try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
355 try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
356 try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
357 try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
358 try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
359 try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
360 try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
361 try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
362}
363
364test "floatundidf" {
365 try test__floatundidf(0, 0.0);
366 try test__floatundidf(1, 1.0);
367 try test__floatundidf(2, 2.0);
368 try test__floatundidf(20, 20.0);
369 try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
370 try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
371 try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
372 try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
373 try test__floatundidf(0x8000008000000000, 0x1.000001p+63);
374 try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63);
375 try test__floatundidf(0x8000010000000000, 0x1.000002p+63);
376 try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63);
377 try test__floatundidf(0x8000000000000000, 0x1p+63);
378 try test__floatundidf(0x8000000000000001, 0x1p+63);
379 try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
380 try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
381 try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
382 try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
383 try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
384 try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
385 try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
386 try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
387 try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
388 try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
389 try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
390 try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
391 try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
392 try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
393 try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
394 try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
395 try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
396 try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
397 try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
398 try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
399 try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
400 try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
401 try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
402 try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
403 try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
404 try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
405}
406
407fn test__floattidf(a: i128, expected: f64) !void {
408 const x = __floattidf(a);
349test f64_floatFromInt_i64 {
350 try test_f64_floatFromInt_i64(0, 0.0);
351 try test_f64_floatFromInt_i64(1, 1.0);
352 try test_f64_floatFromInt_i64(2, 2.0);
353 try test_f64_floatFromInt_i64(20, 20.0);
354 try test_f64_floatFromInt_i64(-1, -1.0);
355 try test_f64_floatFromInt_i64(-2, -2.0);
356 try test_f64_floatFromInt_i64(-20, -20.0);
357 try test_f64_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
358 try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
359 try test_f64_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
360 try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
361 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62);
362 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62);
363 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62);
364 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62);
365 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63);
366 try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001
367 try test_f64_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
368 try test_f64_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
369 try test_f64_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBACp+50);
370 try test_f64_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
371 try test_f64_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBBp+50);
372 try test_f64_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
373 try test_f64_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCB98p+50);
374 try test_f64_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
375 try test_f64_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
376 try test_f64_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
377 try test_f64_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB9p+50);
378 try test_f64_floatFromInt_i64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
379 try test_f64_floatFromInt_i64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
380 try test_f64_floatFromInt_i64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
381 try test_f64_floatFromInt_i64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
382 try test_f64_floatFromInt_i64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
383 try test_f64_floatFromInt_i64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
384 try test_f64_floatFromInt_i64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
385 try test_f64_floatFromInt_i64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
386 try test_f64_floatFromInt_i64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
387 try test_f64_floatFromInt_i64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
388 try test_f64_floatFromInt_i64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
389 try test_f64_floatFromInt_i64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
390 try test_f64_floatFromInt_i64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
391 try test_f64_floatFromInt_i64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
392 try test_f64_floatFromInt_i64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
393}
394
395test f64_floatFromInt_u64 {
396 try test_f64_floatFromInt_u64(0, 0.0);
397 try test_f64_floatFromInt_u64(1, 1.0);
398 try test_f64_floatFromInt_u64(2, 2.0);
399 try test_f64_floatFromInt_u64(20, 20.0);
400 try test_f64_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
401 try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
402 try test_f64_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
403 try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
404 try test_f64_floatFromInt_u64(0x8000008000000000, 0x1.000001p+63);
405 try test_f64_floatFromInt_u64(0x8000000000000800, 0x1.0000000000001p+63);
406 try test_f64_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63);
407 try test_f64_floatFromInt_u64(0x8000000000001000, 0x1.0000000000002p+63);
408 try test_f64_floatFromInt_u64(0x8000000000000000, 0x1p+63);
409 try test_f64_floatFromInt_u64(0x8000000000000001, 0x1p+63);
410 try test_f64_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50);
411 try test_f64_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
412 try test_f64_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBACp+50);
413 try test_f64_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
414 try test_f64_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBBp+50);
415 try test_f64_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
416 try test_f64_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCB98p+50);
417 try test_f64_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
418 try test_f64_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
419 try test_f64_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
420 try test_f64_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB9p+50);
421 try test_f64_floatFromInt_u64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
422 try test_f64_floatFromInt_u64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
423 try test_f64_floatFromInt_u64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
424 try test_f64_floatFromInt_u64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
425 try test_f64_floatFromInt_u64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
426 try test_f64_floatFromInt_u64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
427 try test_f64_floatFromInt_u64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
428 try test_f64_floatFromInt_u64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
429 try test_f64_floatFromInt_u64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
430 try test_f64_floatFromInt_u64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
431 try test_f64_floatFromInt_u64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
432 try test_f64_floatFromInt_u64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
433 try test_f64_floatFromInt_u64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
434 try test_f64_floatFromInt_u64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
435 try test_f64_floatFromInt_u64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
436}
437
438fn test_f64_floatFromInt_i128(a: i128, expected: f64) !void {
439 const x = f64_floatFromInt_i128(a);
409440 try testing.expect(x == expected);
410441}
411442
412fn test__floatuntidf(a: u128, expected: f64) !void {
413 const x = __floatuntidf(a);
443fn test_f64_floatFromInt_u128(a: u128, expected: f64) !void {
444 const x = f64_floatFromInt_u128(a);
414445 try testing.expect(x == expected);
415446}
416447
417test "floattidf" {
418 try test__floattidf(0, 0.0);
419
420 try test__floattidf(1, 1.0);
421 try test__floattidf(2, 2.0);
422 try test__floattidf(20, 20.0);
423 try test__floattidf(-1, -1.0);
424 try test__floattidf(-2, -2.0);
425 try test__floattidf(-20, -20.0);
426
427 try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
428 try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
429 try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
430 try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
431
432 try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
433 try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
434 try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
435 try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
436
437 try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
438 try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127);
439
440 try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
441
442 try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
443 try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
444 try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
445 try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
446 try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
447
448 try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
449 try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
450 try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
451 try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
452 try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
453
454 try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
455 try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
456 try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
457 try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
458 try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
459 try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
460 try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
461 try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
462 try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
463 try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
464 try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
465 try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
466 try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
467 try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
468 try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
469
470 try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
471 try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
472 try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
473 try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
474 try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
475 try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
476 try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
477 try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
478 try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
479 try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
480 try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
481 try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
482 try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
483 try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
484 try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
485}
486
487test "floatuntidf" {
488 try test__floatuntidf(0, 0.0);
489
490 try test__floatuntidf(1, 1.0);
491 try test__floatuntidf(2, 2.0);
492 try test__floatuntidf(20, 20.0);
493
494 try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
495 try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
496 try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
497 try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
498
499 try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
500 try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127);
501 try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
502 try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127);
503
504 try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
505 try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127);
506
507 try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
508
509 try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
510 try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
511 try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
512 try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
513 try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
514
515 try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
516 try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
517 try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
518 try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
519 try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
520
521 try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
522 try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
523 try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
524 try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
525 try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
526 try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
527 try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
528 try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
529 try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
530 try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
531 try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
532 try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
533 try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
534 try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
535 try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
536
537 try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
538 try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
539 try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
540 try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
541 try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
542 try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
543 try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
544 try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
545 try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
546 try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
547 try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
548 try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
549 try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
550 try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
551 try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
552}
553
554fn test__floatsitf(a: i32, expected: u128) !void {
555 const r = __floatsitf(a);
448test f64_floatFromInt_i128 {
449 try test_f64_floatFromInt_i128(0, 0.0);
450
451 try test_f64_floatFromInt_i128(1, 1.0);
452 try test_f64_floatFromInt_i128(2, 2.0);
453 try test_f64_floatFromInt_i128(20, 20.0);
454 try test_f64_floatFromInt_i128(-1, -1.0);
455 try test_f64_floatFromInt_i128(-2, -2.0);
456 try test_f64_floatFromInt_i128(-20, -20.0);
457
458 try test_f64_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
459 try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
460 try test_f64_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
461 try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
462
463 try test_f64_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
464 try test_f64_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
465 try test_f64_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
466 try test_f64_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
467
468 try test_f64_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
469 try test_f64_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.000000p+127);
470
471 try test_f64_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
472
473 try test_f64_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
474 try test_f64_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
475 try test_f64_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
476 try test_f64_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
477 try test_f64_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
478
479 try test_f64_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
480 try test_f64_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
481 try test_f64_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
482 try test_f64_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
483 try test_f64_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
484
485 try test_f64_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
486 try test_f64_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
487 try test_f64_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
488 try test_f64_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
489 try test_f64_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
490 try test_f64_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
491 try test_f64_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
492 try test_f64_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
493 try test_f64_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
494 try test_f64_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
495 try test_f64_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
496 try test_f64_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
497 try test_f64_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
498 try test_f64_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
499 try test_f64_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
500
501 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
502 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
503 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
504 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
505 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
506 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
507 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
508 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
509 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
510 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
511 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
512 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
513 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
514 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
515 try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
516}
517
518test f64_floatFromInt_u128 {
519 try test_f64_floatFromInt_u128(0, 0.0);
520
521 try test_f64_floatFromInt_u128(1, 1.0);
522 try test_f64_floatFromInt_u128(2, 2.0);
523 try test_f64_floatFromInt_u128(20, 20.0);
524
525 try test_f64_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
526 try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
527 try test_f64_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
528 try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
529
530 try test_f64_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127);
531 try test_f64_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127);
532 try test_f64_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127);
533 try test_f64_floatFromInt_u128(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127);
534
535 try test_f64_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127);
536 try test_f64_floatFromInt_u128(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127);
537
538 try test_f64_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
539
540 try test_f64_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
541 try test_f64_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
542 try test_f64_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
543 try test_f64_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
544 try test_f64_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
545
546 try test_f64_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
547 try test_f64_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
548 try test_f64_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
549 try test_f64_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
550 try test_f64_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
551
552 try test_f64_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
553 try test_f64_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57);
554 try test_f64_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57);
555 try test_f64_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57);
556 try test_f64_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57);
557 try test_f64_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57);
558 try test_f64_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57);
559 try test_f64_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57);
560 try test_f64_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57);
561 try test_f64_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57);
562 try test_f64_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57);
563 try test_f64_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57);
564 try test_f64_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57);
565 try test_f64_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57);
566 try test_f64_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
567
568 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
569 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121);
570 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121);
571 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121);
572 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121);
573 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121);
574 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121);
575 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121);
576 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121);
577 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121);
578 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121);
579 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121);
580 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121);
581 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121);
582 try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
583}
584
585fn test_f128_floatFromInt_i32(a: i32, expected: u128) !void {
586 const r = f128_floatFromInt_i32(a);
556587 try std.testing.expect(@as(u128, @bitCast(r)) == expected);
557588}
558589
559test "floatsitf" {
560 try test__floatsitf(0, 0);
561 try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
562 try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000);
563 try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000);
564 try test__floatsitf(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000);
565 try test__floatsitf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000);
566}
567
568fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
569 const x = __floatunsitf(a);
590fn test_f128_floatFromInt_u32(a: u32, expected_hi: u64, expected_lo: u64) !void {
591 const x = f128_floatFromInt_u32(a);
570592
571593 const x_repr: u128 = @bitCast(x);
572594 const x_hi: u64 = @intCast(x_repr >> 64);
......@@ -581,24 +603,32 @@ fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
581603 return;
582604 }
583605 }
606 return error.TestFailure;
607}
584608
585 @panic("__floatunsitf test failure");
609test f128_floatFromInt_i32 {
610 try test_f128_floatFromInt_i32(0, 0);
611 try test_f128_floatFromInt_i32(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
612 try test_f128_floatFromInt_i32(0x12345678, 0x401b2345678000000000000000000000);
613 try test_f128_floatFromInt_i32(-0x12345678, 0xc01b2345678000000000000000000000);
614 try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000);
615 try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000);
586616}
587617
588test "floatunsitf" {
589 try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0);
590 try test__floatunsitf(0, 0x0, 0x0);
591 try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0);
592 try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0);
618test f128_floatFromInt_u32 {
619 try test_f128_floatFromInt_u32(0x7fffffff, 0x401dfffffffc0000, 0x0);
620 try test_f128_floatFromInt_u32(0, 0x0, 0x0);
621 try test_f128_floatFromInt_u32(0xffffffff, 0x401efffffffe0000, 0x0);
622 try test_f128_floatFromInt_u32(0x12345678, 0x401b234567800000, 0x0);
593623}
594624
595fn test__floatditf(a: i64, expected: f128) !void {
596 const x = __floatditf(a);
625fn test_f128_floatFromInt_i64(a: i64, expected: f128) !void {
626 const x = f128_floatFromInt_i64(a);
597627 try testing.expect(x == expected);
598628}
599629
600fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
601 const x = __floatunditf(a);
630fn test_f128_floatFromInt_u64(a: u64, expected_hi: u64, expected_lo: u64) !void {
631 const x = f128_floatFromInt_u64(a);
602632
603633 const x_repr: u128 = @bitCast(x);
604634 const x_hi: u64 = @intCast(x_repr >> 64);
......@@ -613,208 +643,207 @@ fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
613643 return;
614644 }
615645 }
616
617 @panic("__floatunditf test failure");
618}
619
620test "floatditf" {
621 try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000));
622 try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000));
623 try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0));
624 try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0));
625 try test__floatditf(0x0, make_tf(0x0, 0x0));
626 try test__floatditf(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));
627 try test__floatditf(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));
628 try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
629 try test__floatditf(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));
630}
631
632test "floatunditf" {
633 try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);
634 try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);
635 try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0);
636 try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);
637 try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);
638 try test__floatunditf(0x2, 0x4000000000000000, 0x0);
639 try test__floatunditf(0x1, 0x3fff000000000000, 0x0);
640 try test__floatunditf(0x0, 0x0, 0x0);
641}
642
643fn test__floattitf(a: i128, expected: f128) !void {
644 const x = __floattitf(a);
646 return error.TestFailure;
647}
648
649test f128_floatFromInt_i64 {
650 try test_f128_floatFromInt_i64(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000));
651 try test_f128_floatFromInt_i64(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000));
652 try test_f128_floatFromInt_i64(0x2, make_tf(0x4000000000000000, 0x0));
653 try test_f128_floatFromInt_i64(0x1, make_tf(0x3fff000000000000, 0x0));
654 try test_f128_floatFromInt_i64(0x0, make_tf(0x0, 0x0));
655 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));
656 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));
657 try test_f128_floatFromInt_i64(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
658 try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));
659}
660
661test f128_floatFromInt_u64 {
662 try test_f128_floatFromInt_u64(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000);
663 try test_f128_floatFromInt_u64(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000);
664 try test_f128_floatFromInt_u64(0x8000000000000000, 0x403e000000000000, 0x0);
665 try test_f128_floatFromInt_u64(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000);
666 try test_f128_floatFromInt_u64(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000);
667 try test_f128_floatFromInt_u64(0x2, 0x4000000000000000, 0x0);
668 try test_f128_floatFromInt_u64(0x1, 0x3fff000000000000, 0x0);
669 try test_f128_floatFromInt_u64(0x0, 0x0, 0x0);
670}
671
672fn test_f128_floatFromInt_i128(a: i128, expected: f128) !void {
673 const x = f128_floatFromInt_i128(a);
645674 try testing.expect(x == expected);
646675}
647676
648fn test__floatuntitf(a: u128, expected: f128) !void {
649 const x = __floatuntitf(a);
677fn test_f128_floatFromInt_u128(a: u128, expected: f128) !void {
678 const x = f128_floatFromInt_u128(a);
650679 try testing.expect(x == expected);
651680}
652681
653test "floattitf" {
654 try test__floattitf(0, 0.0);
655
656 try test__floattitf(1, 1.0);
657 try test__floattitf(2, 2.0);
658 try test__floattitf(20, 20.0);
659 try test__floattitf(-1, -1.0);
660 try test__floattitf(-2, -2.0);
661 try test__floattitf(-20, -20.0);
662
663 try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
664 try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
665 try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
666 try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
667
668 try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
669 try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
670 try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
671 try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
672
673 try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
674 try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126);
675
676 try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
677
678 try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
679 try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
680 try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
681 try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
682 try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
683
684 try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
685 try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
686 try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
687 try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
688 try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
689
690 try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
691 try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
692 try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
693 try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
694 try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
695 try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
696 try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
697 try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
698 try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
699 try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
700 try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
701 try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
702 try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
703 try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
704 try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
705
706 try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
707 try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
708 try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
709 try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
710 try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
711 try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
712 try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
713 try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
714 try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
715 try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
716 try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
717 try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
718 try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
719 try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
720 try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
721
722 try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
723
724 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
725 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
726 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
727 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
728 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
729 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
730 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
731 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
732 try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
733}
734
735test "floatuntitf" {
736 try test__floatuntitf(0, 0.0);
737
738 try test__floatuntitf(1, 1.0);
739 try test__floatuntitf(2, 2.0);
740 try test__floatuntitf(20, 20.0);
741
742 try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
743 try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
744 try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
745 try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
746 try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59);
747 try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60);
748 try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60);
749
750 try test__floatuntitf(0x8000008000000000, 0x8.000008p+60);
751 try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60);
752 try test__floatuntitf(0x8000010000000000, 0x8.00001p+60);
753 try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60);
754
755 try test__floatuntitf(0x8000000000000000, 0x8p+60);
756 try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60);
757
758 try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
759
760 try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
761 try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
762 try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
763 try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50);
764 try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
765
766 try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50);
767 try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
768 try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
769 try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
770 try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50);
771
772 try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
773 try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
774 try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
775 try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
776 try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
777 try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
778 try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
779 try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
780 try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
781 try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
782 try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
783 try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
784 try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
785 try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
786 try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
787
788 try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
789 try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
790 try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
791 try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
792 try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
793 try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
794 try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
795 try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
796 try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
797 try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
798 try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
799 try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
800 try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
801 try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
802 try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
803
804 try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
805
806 try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127);
807 try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128);
808
809 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
810 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
811 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
812 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
813 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
814 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
815 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
816 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
817 try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
682test f128_floatFromInt_i128 {
683 try test_f128_floatFromInt_i128(0, 0.0);
684
685 try test_f128_floatFromInt_i128(1, 1.0);
686 try test_f128_floatFromInt_i128(2, 2.0);
687 try test_f128_floatFromInt_i128(20, 20.0);
688 try test_f128_floatFromInt_i128(-1, -1.0);
689 try test_f128_floatFromInt_i128(-2, -2.0);
690 try test_f128_floatFromInt_i128(-20, -20.0);
691
692 try test_f128_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
693 try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
694 try test_f128_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
695 try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
696
697 try test_f128_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126);
698 try test_f128_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126);
699 try test_f128_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126);
700 try test_f128_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126);
701
702 try test_f128_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127);
703 try test_f128_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126);
704
705 try test_f128_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
706
707 try test_f128_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
708 try test_f128_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
709 try test_f128_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
710 try test_f128_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
711 try test_f128_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
712
713 try test_f128_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
714 try test_f128_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
715 try test_f128_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
716 try test_f128_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
717 try test_f128_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
718
719 try test_f128_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
720 try test_f128_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
721 try test_f128_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
722 try test_f128_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
723 try test_f128_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
724 try test_f128_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
725 try test_f128_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
726 try test_f128_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
727 try test_f128_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
728 try test_f128_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
729 try test_f128_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
730 try test_f128_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
731 try test_f128_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
732 try test_f128_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
733 try test_f128_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
734
735 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
736 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
737 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
738 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
739 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
740 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
741 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
742 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
743 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
744 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
745 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
746 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
747 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
748 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
749 try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
750
751 try test_f128_floatFromInt_i128(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
752
753 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
754 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
755 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
756 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
757 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
758 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
759 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
760 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
761 try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
762}
763
764test f128_floatFromInt_u128 {
765 try test_f128_floatFromInt_u128(0, 0.0);
766
767 try test_f128_floatFromInt_u128(1, 1.0);
768 try test_f128_floatFromInt_u128(2, 2.0);
769 try test_f128_floatFromInt_u128(20, 20.0);
770
771 try test_f128_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
772 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
773 try test_f128_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
774 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
775 try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59);
776 try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60);
777 try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60);
778
779 try test_f128_floatFromInt_u128(0x8000008000000000, 0x8.000008p+60);
780 try test_f128_floatFromInt_u128(0x8000000000000800, 0x8.0000000000008p+60);
781 try test_f128_floatFromInt_u128(0x8000010000000000, 0x8.00001p+60);
782 try test_f128_floatFromInt_u128(0x8000000000001000, 0x8.000000000001p+60);
783
784 try test_f128_floatFromInt_u128(0x8000000000000000, 0x8p+60);
785 try test_f128_floatFromInt_u128(0x8000000000000001, 0x8.000000000000001p+60);
786
787 try test_f128_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50);
788
789 try test_f128_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
790 try test_f128_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50);
791 try test_f128_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50);
792 try test_f128_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50);
793 try test_f128_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50);
794
795 try test_f128_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50);
796 try test_f128_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50);
797 try test_f128_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50);
798 try test_f128_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50);
799 try test_f128_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50);
800
801 try test_f128_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57);
802 try test_f128_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57);
803 try test_f128_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57);
804 try test_f128_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57);
805 try test_f128_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57);
806 try test_f128_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57);
807 try test_f128_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57);
808 try test_f128_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57);
809 try test_f128_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57);
810 try test_f128_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57);
811 try test_f128_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57);
812 try test_f128_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57);
813 try test_f128_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57);
814 try test_f128_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57);
815 try test_f128_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57);
816
817 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121);
818 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121);
819 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121);
820 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121);
821 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121);
822 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121);
823 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121);
824 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121);
825 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121);
826 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121);
827 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121);
828 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121);
829 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121);
830 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121);
831 try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121);
832
833 try test_f128_floatFromInt_u128(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63);
834
835 try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127);
836 try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128);
837
838 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124);
839 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124);
840 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124);
841 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124);
842 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124);
843 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124);
844 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124);
845 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124);
846 try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124);
818847}
819848
820849fn make_ti(high: u64, low: u64) i128 {
......@@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 {
838867 return @bitCast(result);
839868}
840869
841test "conversion to f16" {
842 try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0);
843 try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0);
844 try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504);
845 try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16));
846}
847
848test "conversion to f32" {
849 try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0);
850 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0);
851 try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0);
852 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24));
853 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact
854 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even
855 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact
856 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even
857 try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact
858}
859
860test "conversion to f80" {
861 const floatFromInt = @import("./float_from_int.zig").floatFromInt;
862
863 try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12);
864 try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0);
865 try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1);
866
867 try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0);
868 try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0);
869 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24));
870 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64));
871 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact
872 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down
873 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact
874 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up
875
876 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up
877 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1))) == math.maxInt(u65) + 1); // Exact
878 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2))) == math.maxInt(u65) + 1); // Rounds down
879 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3))) == math.maxInt(u65) + 1); // Tie - Rounds down
880 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4))) == math.maxInt(u65) + 5); // Rounds up
881 try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5))) == math.maxInt(u65) + 5); // Exact
870test f16_floatFromInt_u32 {
871 try testing.expect(f16_floatFromInt_u32(0) == 0.0);
872 try testing.expect(f16_floatFromInt_u32(1) == 1.0);
873 try testing.expect(f16_floatFromInt_u32(65504) == 65504);
874 try testing.expect(f16_floatFromInt_u32(65504 + (1 << 4)) == math.inf(f16));
875}
876
877test f80_floatFromInt_u32 {
878 try testing.expect(f80_floatFromInt_u32(0) == 0.0);
879 try testing.expect(f80_floatFromInt_u32(1) == 1.0);
880 try testing.expect(f80_floatFromInt_u32(math.maxInt(u24) + 0) == math.maxInt(u24));
881}
882
883test f80_floatFromInt_u64 {
884 try testing.expect(f80_floatFromInt_u64(math.maxInt(u64) + 0) == math.maxInt(u64) + 0);
885}
886
887test f80_floatFromInt_i128 {
888 try testing.expect(f80_floatFromInt_i128(-12) == -12);
889}
890
891test f80_floatFromInt_u128 {
892 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1);
893
894 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 0) == math.maxInt(u64));
895 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); // Exact
896 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 2) == math.maxInt(u64) + 1); // Rounds down
897 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 3) == math.maxInt(u64) + 3); // Tie - Exact
898 try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 4) == math.maxInt(u64) + 5); // Rounds up
899
900 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 0) == math.maxInt(u65) + 1); // Rounds up
901 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 1) == math.maxInt(u65) + 1); // Exact
902 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 2) == math.maxInt(u65) + 1); // Rounds down
903 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 3) == math.maxInt(u65) + 1); // Tie - Rounds down
904 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 4) == math.maxInt(u65) + 5); // Rounds up
905 try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 5) == math.maxInt(u65) + 5); // Exact
882906}
lib/compiler_rt/floatdidf.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_l2d, "__aeabi_l2d");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__floatdidf, "__i64tod");
12 }
13 symbol(&__floatdidf, "__floatdidf");
14 }
15}
16
17pub fn __floatdidf(a: i64) callconv(.c) f64 {
18 return floatFromInt(f64, a);
19}
20
21fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 {
22 return floatFromInt(f64, a);
23}
lib/compiler_rt/floatdihf.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3
4comptime {
5 symbol(&__floatdihf, "__floatdihf");
6}
7
8fn __floatdihf(a: i64) callconv(.c) f16 {
9 return floatFromInt(f16, a);
10}
lib/compiler_rt/floatdisf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_l2f, "__aeabi_l2f");
8 } else {
9 if (compiler_rt.want_windows_arm_abi) {
10 symbol(&__floatdisf, "__i64tos");
11 }
12 symbol(&__floatdisf, "__floatdisf");
13 }
14}
15
16pub fn __floatdisf(a: i64) callconv(.c) f32 {
17 return floatFromInt(f32, a);
18}
19
20fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 {
21 return floatFromInt(f32, a);
22}
lib/compiler_rt/floatditf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatditf, "__floatdikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_xtoq, "_Qp_xtoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__floatditf, "_Q_lltoq");
12 }
13 symbol(&__floatditf, "__floatditf");
14}
15
16pub fn __floatditf(a: i64) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatdixf.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3
4comptime {
5 symbol(&__floatdixf, "__floatdixf");
6}
7
8fn __floatdixf(a: i64) callconv(.c) f80 {
9 return floatFromInt(f80, a);
10}
lib/compiler_rt/floateidf.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6const symbol = @import("../compiler_rt.zig").symbol;
7
8comptime {
9 symbol(&__floateidf, "__floateidf");
10}
11
12pub fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) f64 {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a[0..byte_size])));
15}
lib/compiler_rt/floateihf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floateihf, "__floateihf");
9}
10
11pub fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) f16 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floateisf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floateisf, "__floateisf");
9}
10
11pub fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) f32 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floateitf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floateitf, "__floateitf");
9}
10
11pub fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) f128 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floateixf.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
7
8comptime {
9 symbol(&__floateixf, "__floateixf");
10}
11
12pub fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) f80 {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a[0..byte_size])));
15}
lib/compiler_rt/floatsidf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_i2d, "__aeabi_i2d");
8 } else {
9 symbol(&__floatsidf, "__floatsidf");
10 }
11}
12
13pub fn __floatsidf(a: i32) callconv(.c) f64 {
14 return floatFromInt(f64, a);
15}
16
17fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return floatFromInt(f64, a);
19}
lib/compiler_rt/floatsihf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatsihf, "__floatsihf");
7}
8
9fn __floatsihf(a: i32) callconv(.c) f16 {
10 return floatFromInt(f16, a);
11}
lib/compiler_rt/floatsisf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_i2f, "__aeabi_i2f");
8 } else {
9 symbol(&__floatsisf, "__floatsisf");
10 }
11}
12
13pub fn __floatsisf(a: i32) callconv(.c) f32 {
14 return floatFromInt(f32, a);
15}
16
17fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return floatFromInt(f32, a);
19}
lib/compiler_rt/floatsitf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatsitf, "__floatsikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_itoq, "_Qp_itoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__floatsitf, "_Q_itoq");
12 }
13 symbol(&__floatsitf, "__floatsitf");
14}
15
16pub fn __floatsitf(a: i32) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatsixf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__floatsixf, "__floatsixf");
7}
8
9fn __floatsixf(a: i32) callconv(.c) f80 {
10 return floatFromInt(f80, a);
11}
lib/compiler_rt/floattidf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floattidf, "__floattidf");
7}
8
9pub fn __floattidf(a: i128) callconv(.c) f64 {
10 return floatFromInt(f64, a);
11}
lib/compiler_rt/floattihf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floattihf, "__floattihf");
8}
9
10pub fn __floattihf(a: i128) callconv(.c) f16 {
11 return floatFromInt(f16, a);
12}
lib/compiler_rt/floattisf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__floattisf, "__floattisf");
7}
8
9pub fn __floattisf(a: i128) callconv(.c) f32 {
10 return floatFromInt(f32, a);
11}
lib/compiler_rt/floattitf.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_ppc_abi)
7 symbol(&__floattitf, "__floattikf");
8 symbol(&__floattitf, "__floattitf");
9}
10
11pub fn __floattitf(a: i128) callconv(.c) f128 {
12 return floatFromInt(f128, a);
13}
lib/compiler_rt/floattixf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floattixf, "__floattixf");
8}
9
10pub fn __floattixf(a: i128) callconv(.c) f80 {
11 return floatFromInt(f80, a);
12}
lib/compiler_rt/floatundidf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_ul2d, "__aeabi_ul2d");
8 } else {
9 if (compiler_rt.want_windows_arm_abi) {
10 symbol(&__floatundidf, "__u64tod");
11 }
12 symbol(&__floatundidf, "__floatundidf");
13 }
14}
15
16pub fn __floatundidf(a: u64) callconv(.c) f64 {
17 return floatFromInt(f64, a);
18}
19
20fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 {
21 return floatFromInt(f64, a);
22}
lib/compiler_rt/floatundihf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatundihf, "__floatundihf");
7}
8
9fn __floatundihf(a: u64) callconv(.c) f16 {
10 return floatFromInt(f16, a);
11}
lib/compiler_rt/floatundisf.zig deleted-23
......@@ -1,23 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 symbol(&__aeabi_ul2f, "__aeabi_ul2f");
9 } else {
10 if (compiler_rt.want_windows_arm_abi) {
11 symbol(&__floatundisf, "__u64tos");
12 }
13 symbol(&__floatundisf, "__floatundisf");
14 }
15}
16
17pub fn __floatundisf(a: u64) callconv(.c) f32 {
18 return floatFromInt(f32, a);
19}
20
21fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 {
22 return floatFromInt(f32, a);
23}
lib/compiler_rt/floatunditf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatunditf, "__floatundikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_uxtoq, "_Qp_uxtoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 @export(&__floatunditf, "_Q_ulltoq");
12 }
13 symbol(&__floatunditf, "__floatunditf");
14}
15
16pub fn __floatunditf(a: u64) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatundixf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatundixf, "__floatundixf");
7}
8
9fn __floatundixf(a: u64) callconv(.c) f80 {
10 return floatFromInt(f80, a);
11}
lib/compiler_rt/floatuneidf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneidf, "__floatuneidf");
9}
10
11pub fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) f64 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatuneihf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneihf, "__floatuneihf");
9}
10
11pub fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) f16 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatuneisf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneisf, "__floatuneisf");
9}
10
11pub fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) f32 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatuneitf.zig deleted-15
......@@ -1,15 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4
5const symbol = @import("../compiler_rt.zig").symbol;
6const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
7
8comptime {
9 symbol(&__floatuneitf, "__floatuneitf");
10}
11
12pub fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) f128 {
13 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
14 return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
15}
lib/compiler_rt/floatuneixf.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt;
6
7comptime {
8 symbol(&__floatuneixf, "__floatuneixf");
9}
10
11pub fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) f80 {
12 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
13 return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a[0..byte_size])));
14}
lib/compiler_rt/floatunsidf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_ui2d, "__aeabi_ui2d");
8 } else {
9 symbol(&__floatunsidf, "__floatunsidf");
10 }
11}
12
13pub fn __floatunsidf(a: u32) callconv(.c) f64 {
14 return floatFromInt(f64, a);
15}
16
17fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return floatFromInt(f64, a);
19}
lib/compiler_rt/floatunsihf.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3
4comptime {
5 symbol(&__floatunsihf, "__floatunsihf");
6}
7
8pub fn __floatunsihf(a: u32) callconv(.c) f16 {
9 return floatFromInt(f16, a);
10}
lib/compiler_rt/floatunsisf.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_ui2f, "__aeabi_ui2f");
8 } else {
9 symbol(&__floatunsisf, "__floatunsisf");
10 }
11}
12
13pub fn __floatunsisf(a: u32) callconv(.c) f32 {
14 return floatFromInt(f32, a);
15}
16
17fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return floatFromInt(f32, a);
19}
lib/compiler_rt/floatunsitf.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__floatunsitf, "__floatunsikf");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_uitoq, "_Qp_uitoq");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__floatunsitf, "_Q_utoq");
12 }
13 symbol(&__floatunsitf, "__floatunsitf");
14}
15
16pub fn __floatunsitf(a: u32) callconv(.c) f128 {
17 return floatFromInt(f128, a);
18}
19
20fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void {
21 c.* = floatFromInt(f128, a);
22}
lib/compiler_rt/floatunsixf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatunsixf, "__floatunsixf");
7}
8
9fn __floatunsixf(a: u32) callconv(.c) f80 {
10 return floatFromInt(f80, a);
11}
lib/compiler_rt/floatuntidf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 symbol(&__floatuntidf, "__floatuntidf");
7}
8
9pub fn __floatuntidf(a: u128) callconv(.c) f64 {
10 return floatFromInt(f64, a);
11}
lib/compiler_rt/floatuntihf.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const floatFromInt = @import("./float_from_int.zig").floatFromInt;
4
5comptime {
6 symbol(&__floatuntihf, "__floatuntihf");
7}
8
9pub fn __floatuntihf(a: u128) callconv(.c) f16 {
10 return floatFromInt(f16, a);
11}
lib/compiler_rt/floatuntisf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floatuntisf, "__floatuntisf");
8}
9
10pub fn __floatuntisf(a: u128) callconv(.c) f32 {
11 return floatFromInt(f32, a);
12}
lib/compiler_rt/floatuntitf.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const floatFromInt = @import("./float_from_int.zig").floatFromInt;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi)
7 symbol(&__floatuntitf, "__floatuntikf");
8 symbol(&__floatuntitf, "__floatuntitf");
9}
10
11pub fn __floatuntitf(a: u128) callconv(.c) f128 {
12 return floatFromInt(f128, a);
13}
lib/compiler_rt/floatuntixf.zig deleted-12
......@@ -1,12 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const floatFromInt = @import("./float_from_int.zig").floatFromInt;
5
6comptime {
7 symbol(&__floatuntixf, "__floatuntixf");
8}
9
10pub fn __floatuntixf(a: u128) callconv(.c) f80 {
11 return floatFromInt(f80, a);
12}
lib/compiler_rt/floor_ceil.zig+173-159
......@@ -15,7 +15,7 @@ const mem = std.mem;
1515const expect = std.testing.expect;
1616
1717const compiler_rt = @import("../compiler_rt.zig");
18const symbol = @import("../compiler_rt.zig").symbol;
18const symbol = compiler_rt.symbol;
1919
2020comptime {
2121 // floor
......@@ -23,10 +23,7 @@ comptime {
2323 symbol(&floorf, "floorf");
2424 symbol(&floor, "floor");
2525 symbol(&__floorx, "__floorx");
26 if (compiler_rt.want_ppc_abi) {
27 symbol(&floorq, "floorf128");
28 }
29 symbol(&floorq, "floorq");
26 symbol(&floorq, "floorf128");
3027 symbol(&floorl, "floorl");
3128
3229 // ceil
......@@ -34,59 +31,96 @@ comptime {
3431 symbol(&ceilf, "ceilf");
3532 symbol(&ceil, "ceil");
3633 symbol(&__ceilx, "__ceilx");
37 if (compiler_rt.want_ppc_abi) {
38 symbol(&ceilq, "ceilf128");
39 }
40 symbol(&ceilq, "ceilq");
34 symbol(&ceilq, "ceilf128");
4135 symbol(&ceill, "ceill");
4236}
4337
44pub fn __floorh(x: f16) callconv(.c) f16 {
38fn __floorh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
39 return compiler_rt.f16.toAbi(floor_f16(compiler_rt.f16.fromAbi(x)));
40}
41pub fn floor_f16(x: f16) f16 {
4542 return impl(f16, .floor, x);
4643}
4744
48pub fn floorf(x: f32) callconv(.c) f32 {
45fn floorf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
46 return compiler_rt.f32.toAbi(floor_f32(compiler_rt.f32.fromAbi(x)));
47}
48pub fn floor_f32(x: f32) f32 {
4949 return impl(f32, .floor, x);
5050}
5151
52pub fn floor(x: f64) callconv(.c) f64 {
52fn floor(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
53 return compiler_rt.f64.toAbi(floor_f64(compiler_rt.f64.fromAbi(x)));
54}
55pub fn floor_f64(x: f64) f64 {
5356 return impl(f64, .floor, x);
5457}
5558
56pub fn __floorx(x: f80) callconv(.c) f80 {
59fn __floorx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
60 return compiler_rt.f80.toAbi(floor_f80(compiler_rt.f80.fromAbi(x)));
61}
62pub fn floor_f80(x: f80) f80 {
5763 return impl(f80, .floor, x);
5864}
5965
60pub fn floorq(x: f128) callconv(.c) f128 {
66fn floorq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
67 return compiler_rt.f128.toAbi(floor_f128(compiler_rt.f128.fromAbi(x)));
68}
69pub fn floor_f128(x: f128) f128 {
6170 return impl(f128, .floor, x);
6271}
6372
6473pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble {
65 return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .floor, x);
74 switch (@typeInfo(c_longdouble).float.bits) {
75 64 => return floor_f64(x),
76 80 => return floor_f80(x),
77 128 => return floor_f128(x),
78 else => comptime unreachable,
79 }
6680}
6781
68pub fn __ceilh(x: f16) callconv(.c) f16 {
82fn __ceilh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
83 return compiler_rt.f16.toAbi(ceil_f16(compiler_rt.f16.fromAbi(x)));
84}
85pub fn ceil_f16(x: f16) f16 {
6986 return impl(f16, .ceil, x);
7087}
7188
72pub fn ceilf(x: f32) callconv(.c) f32 {
89fn ceilf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
90 return compiler_rt.f32.toAbi(ceil_f32(compiler_rt.f32.fromAbi(x)));
91}
92pub fn ceil_f32(x: f32) f32 {
7393 return impl(f32, .ceil, x);
7494}
7595
76pub fn ceil(x: f64) callconv(.c) f64 {
96fn ceil(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
97 return compiler_rt.f64.toAbi(ceil_f64(compiler_rt.f64.fromAbi(x)));
98}
99pub fn ceil_f64(x: f64) f64 {
77100 return impl(f64, .ceil, x);
78101}
79102
80pub fn __ceilx(x: f80) callconv(.c) f80 {
103fn __ceilx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
104 return compiler_rt.f80.toAbi(ceil_f80(compiler_rt.f80.fromAbi(x)));
105}
106pub fn ceil_f80(x: f80) f80 {
81107 return impl(f80, .ceil, x);
82108}
83109
84pub fn ceilq(x: f128) callconv(.c) f128 {
110fn ceilq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
111 return compiler_rt.f128.toAbi(ceil_f128(compiler_rt.f128.fromAbi(x)));
112}
113pub fn ceil_f128(x: f128) f128 {
85114 return impl(f128, .ceil, x);
86115}
87116
88117pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble {
89 return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .ceil, x);
118 switch (@typeInfo(c_longdouble).float.bits) {
119 64 => return ceil_f64(x),
120 80 => return ceil_f80(x),
121 128 => return ceil_f128(x),
122 else => comptime unreachable,
123 }
90124}
91125
92126inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {
......@@ -144,142 +178,122 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {
144178 }
145179}
146180
147test "floor16" {
148 try expect(__floorh(1.3) == 1.0);
149 try expect(__floorh(-1.3) == -2.0);
150 try expect(__floorh(0.2) == 0.0);
151}
152
153test "floor32" {
154 try expect(floorf(1.3) == 1.0);
155 try expect(floorf(-1.3) == -2.0);
156 try expect(floorf(0.2) == 0.0);
157}
158
159test "floor64" {
160 try expect(floor(1.3) == 1.0);
161 try expect(floor(-1.3) == -2.0);
162 try expect(floor(0.2) == 0.0);
163}
164
165test "floor80" {
166 try expect(__floorx(1.3) == 1.0);
167 try expect(__floorx(-1.3) == -2.0);
168 try expect(__floorx(0.2) == 0.0);
169}
170
171test "floor128" {
172 try expect(floorq(1.3) == 1.0);
173 try expect(floorq(-1.3) == -2.0);
174 try expect(floorq(0.2) == 0.0);
175}
176
177test "floor16.special" {
178 try expect(__floorh(0.0) == 0.0);
179 try expect(__floorh(-0.0) == -0.0);
180 try expect(math.isPositiveInf(__floorh(math.inf(f16))));
181 try expect(math.isNegativeInf(__floorh(-math.inf(f16))));
182 try expect(math.isNan(__floorh(math.nan(f16))));
183}
184
185test "floor32.special" {
186 try expect(floorf(0.0) == 0.0);
187 try expect(floorf(-0.0) == -0.0);
188 try expect(math.isPositiveInf(floorf(math.inf(f32))));
189 try expect(math.isNegativeInf(floorf(-math.inf(f32))));
190 try expect(math.isNan(floorf(math.nan(f32))));
191}
192
193test "floor64.special" {
194 try expect(floor(0.0) == 0.0);
195 try expect(floor(-0.0) == -0.0);
196 try expect(math.isPositiveInf(floor(math.inf(f64))));
197 try expect(math.isNegativeInf(floor(-math.inf(f64))));
198 try expect(math.isNan(floor(math.nan(f64))));
199}
200
201test "floor80.special" {
202 try expect(__floorx(0.0) == 0.0);
203 try expect(__floorx(-0.0) == -0.0);
204 try expect(math.isPositiveInf(__floorx(math.inf(f80))));
205 try expect(math.isNegativeInf(__floorx(-math.inf(f80))));
206 try expect(math.isNan(__floorx(math.nan(f80))));
207}
208
209test "floor128.special" {
210 try expect(floorq(0.0) == 0.0);
211 try expect(floorq(-0.0) == -0.0);
212 try expect(math.isPositiveInf(floorq(math.inf(f128))));
213 try expect(math.isNegativeInf(floorq(-math.inf(f128))));
214 try expect(math.isNan(floorq(math.nan(f128))));
215}
216
217test "ceil16" {
218 try expect(__ceilh(1.3) == 2.0);
219 try expect(__ceilh(-1.3) == -1.0);
220 try expect(__ceilh(0.2) == 1.0);
221}
222
223test "ceil32" {
224 try expect(ceilf(1.3) == 2.0);
225 try expect(ceilf(-1.3) == -1.0);
226 try expect(ceilf(0.2) == 1.0);
227}
228
229test "ceil64" {
230 try expect(ceil(1.3) == 2.0);
231 try expect(ceil(-1.3) == -1.0);
232 try expect(ceil(0.2) == 1.0);
233}
234
235test "ceil80" {
236 try expect(__ceilx(1.3) == 2.0);
237 try expect(__ceilx(-1.3) == -1.0);
238 try expect(__ceilx(0.2) == 1.0);
239}
240
241test "ceil128" {
242 try expect(ceilq(1.3) == 2.0);
243 try expect(ceilq(-1.3) == -1.0);
244 try expect(ceilq(0.2) == 1.0);
245}
246
247test "ceil16.special" {
248 try expect(__ceilh(0.0) == 0.0);
249 try expect(__ceilh(-0.0) == -0.0);
250 try expect(math.isPositiveInf(__ceilh(math.inf(f16))));
251 try expect(math.isNegativeInf(__ceilh(-math.inf(f16))));
252 try expect(math.isNan(__ceilh(math.nan(f16))));
253}
254
255test "ceil32.special" {
256 try expect(ceilf(0.0) == 0.0);
257 try expect(ceilf(-0.0) == -0.0);
258 try expect(math.isPositiveInf(ceilf(math.inf(f32))));
259 try expect(math.isNegativeInf(ceilf(-math.inf(f32))));
260 try expect(math.isNan(ceilf(math.nan(f32))));
261}
262
263test "ceil64.special" {
264 try expect(ceil(0.0) == 0.0);
265 try expect(ceil(-0.0) == -0.0);
266 try expect(math.isPositiveInf(ceil(math.inf(f64))));
267 try expect(math.isNegativeInf(ceil(-math.inf(f64))));
268 try expect(math.isNan(ceil(math.nan(f64))));
269}
270
271test "ceil80.special" {
272 try expect(__ceilx(0.0) == 0.0);
273 try expect(__ceilx(-0.0) == -0.0);
274 try expect(math.isPositiveInf(__ceilx(math.inf(f80))));
275 try expect(math.isNegativeInf(__ceilx(-math.inf(f80))));
276 try expect(math.isNan(__ceilx(math.nan(f80))));
277}
278
279test "ceil128.special" {
280 try expect(ceilq(0.0) == 0.0);
281 try expect(ceilq(-0.0) == -0.0);
282 try expect(math.isPositiveInf(ceilq(math.inf(f128))));
283 try expect(math.isNegativeInf(ceilq(-math.inf(f128))));
284 try expect(math.isNan(ceilq(math.nan(f128))));
181test floor_f16 {
182 try expect(floor_f16(1.3) == 1.0);
183 try expect(floor_f16(-1.3) == -2.0);
184 try expect(floor_f16(-0.2) == -1.0);
185 try expect(math.isPositiveZero(floor_f16(0.2)));
186 try expect(math.isPositiveZero(floor_f16(0.0)));
187 try expect(math.isNegativeZero(floor_f16(-0.0)));
188 try expect(math.isPositiveInf(floor_f16(math.inf(f16))));
189 try expect(math.isNegativeInf(floor_f16(-math.inf(f16))));
190 try expect(math.isNan(floor_f16(math.nan(f16))));
191}
192
193test floor_f32 {
194 try expect(floor_f32(1.3) == 1.0);
195 try expect(floor_f32(-1.3) == -2.0);
196 try expect(floor_f32(-0.2) == -1.0);
197 try expect(math.isPositiveZero(floor_f32(0.2)));
198 try expect(math.isPositiveZero(floor_f32(0.0)));
199 try expect(math.isNegativeZero(floor_f32(-0.0)));
200 try expect(math.isPositiveInf(floor_f32(math.inf(f32))));
201 try expect(math.isNegativeInf(floor_f32(-math.inf(f32))));
202 try expect(math.isNan(floor_f32(math.nan(f32))));
203}
204
205test floor_f64 {
206 try expect(floor_f64(1.3) == 1.0);
207 try expect(floor_f64(-1.3) == -2.0);
208 try expect(floor_f64(-0.2) == -1.0);
209 try expect(math.isPositiveZero(floor_f64(0.2)));
210 try expect(math.isPositiveZero(floor_f64(0.0)));
211 try expect(math.isNegativeZero(floor_f64(-0.0)));
212 try expect(math.isPositiveInf(floor_f64(math.inf(f64))));
213 try expect(math.isNegativeInf(floor_f64(-math.inf(f64))));
214 try expect(math.isNan(floor_f64(math.nan(f64))));
215}
216
217test floor_f80 {
218 try expect(floor_f80(1.3) == 1.0);
219 try expect(floor_f80(-1.3) == -2.0);
220 try expect(floor_f80(-0.2) == -1.0);
221 try expect(math.isPositiveZero(floor_f80(0.2)));
222 try expect(math.isPositiveZero(floor_f80(0.0)));
223 try expect(math.isNegativeZero(floor_f80(-0.0)));
224 try expect(math.isPositiveInf(floor_f80(math.inf(f80))));
225 try expect(math.isNegativeInf(floor_f80(-math.inf(f80))));
226 try expect(math.isNan(floor_f80(math.nan(f80))));
227}
228
229test floor_f128 {
230 try expect(floor_f128(1.3) == 1.0);
231 try expect(floor_f128(-1.3) == -2.0);
232 try expect(floor_f128(-0.2) == -1.0);
233 try expect(math.isPositiveZero(floor_f128(0.2)));
234 try expect(math.isPositiveZero(floor_f128(0.0)));
235 try expect(math.isNegativeZero(floor_f128(-0.0)));
236 try expect(math.isPositiveInf(floor_f128(math.inf(f128))));
237 try expect(math.isNegativeInf(floor_f128(-math.inf(f128))));
238 try expect(math.isNan(floor_f128(math.nan(f128))));
239}
240
241test ceil_f16 {
242 try expect(ceil_f16(1.3) == 2.0);
243 try expect(ceil_f16(-1.3) == -1.0);
244 try expect(ceil_f16(0.2) == 1.0);
245 try expect(math.isNegativeZero(ceil_f16(-0.2)));
246 try expect(math.isPositiveZero(ceil_f16(0.0)));
247 try expect(math.isNegativeZero(ceil_f16(-0.0)));
248 try expect(math.isPositiveInf(ceil_f16(math.inf(f16))));
249 try expect(math.isNegativeInf(ceil_f16(-math.inf(f16))));
250 try expect(math.isNan(ceil_f16(math.nan(f16))));
251}
252
253test ceil_f32 {
254 try expect(ceil_f32(1.3) == 2.0);
255 try expect(ceil_f32(-1.3) == -1.0);
256 try expect(ceil_f32(0.2) == 1.0);
257 try expect(math.isNegativeZero(ceil_f32(-0.2)));
258 try expect(math.isPositiveZero(ceil_f32(0.0)));
259 try expect(math.isNegativeZero(ceil_f32(-0.0)));
260 try expect(math.isPositiveInf(ceil_f32(math.inf(f32))));
261 try expect(math.isNegativeInf(ceil_f32(-math.inf(f32))));
262 try expect(math.isNan(ceil_f32(math.nan(f32))));
263}
264
265test ceil_f64 {
266 try expect(ceil_f64(1.3) == 2.0);
267 try expect(ceil_f64(-1.3) == -1.0);
268 try expect(ceil_f64(0.2) == 1.0);
269 try expect(math.isNegativeZero(ceil_f64(-0.2)));
270 try expect(math.isPositiveZero(ceil_f64(0.0)));
271 try expect(math.isNegativeZero(ceil_f64(-0.0)));
272 try expect(math.isPositiveInf(ceil_f64(math.inf(f64))));
273 try expect(math.isNegativeInf(ceil_f64(-math.inf(f64))));
274 try expect(math.isNan(ceil_f64(math.nan(f64))));
275}
276
277test ceil_f80 {
278 try expect(ceil_f80(1.3) == 2.0);
279 try expect(ceil_f80(-1.3) == -1.0);
280 try expect(ceil_f80(0.2) == 1.0);
281 try expect(math.isNegativeZero(ceil_f80(-0.2)));
282 try expect(math.isPositiveZero(ceil_f80(0.0)));
283 try expect(math.isNegativeZero(ceil_f80(-0.0)));
284 try expect(math.isPositiveInf(ceil_f80(math.inf(f80))));
285 try expect(math.isNegativeInf(ceil_f80(-math.inf(f80))));
286 try expect(math.isNan(ceil_f80(math.nan(f80))));
287}
288
289test ceil_f128 {
290 try expect(ceil_f128(1.3) == 2.0);
291 try expect(ceil_f128(-1.3) == -1.0);
292 try expect(ceil_f128(0.2) == 1.0);
293 try expect(math.isNegativeZero(ceil_f128(-0.2)));
294 try expect(math.isPositiveZero(ceil_f128(0.0)));
295 try expect(math.isNegativeZero(ceil_f128(-0.0)));
296 try expect(math.isPositiveInf(ceil_f128(math.inf(f128))));
297 try expect(math.isNegativeInf(ceil_f128(-math.inf(f128))));
298 try expect(math.isNan(ceil_f128(math.nan(f128))));
285299}
lib/compiler_rt/fma.zig+48-36
......@@ -16,19 +16,22 @@ comptime {
1616 symbol(&fmaf, "fmaf");
1717 symbol(&fma, "fma");
1818 symbol(&__fmax, "__fmax");
19 if (compiler_rt.want_ppc_abi) {
20 symbol(&fmaq, "fmaf128");
21 }
22 symbol(&fmaq, "fmaq");
19 symbol(&fmaq, "fmaf128");
2320 symbol(&fmal, "fmal");
2421}
2522
26pub fn __fmah(x: f16, y: f16, z: f16) callconv(.c) f16 {
23fn __fmah(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi, z: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
24 return compiler_rt.f16.toAbi(fma_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y), compiler_rt.f16.fromAbi(z)));
25}
26pub fn fma_f16(x: f16, y: f16, z: f16) f16 {
2727 // TODO: more efficient implementation
28 return @floatCast(fmaf(x, y, z));
28 return @floatCast(fma_f32(x, y, z));
2929}
3030
31pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 {
31fn fmaf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi, z: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
32 return compiler_rt.f32.toAbi(fma_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y), compiler_rt.f32.fromAbi(z)));
33}
34pub fn fma_f32(x: f32, y: f32, z: f32) f32 {
3235 const xy = @as(f64, x) * y;
3336 const xy_z = xy + z;
3437 const u = @as(u64, @bitCast(xy_z));
......@@ -42,8 +45,11 @@ pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 {
4245 }
4346}
4447
48fn fma(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi, z: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
49 return compiler_rt.f64.toAbi(fma_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y), compiler_rt.f64.fromAbi(z)));
50}
4551/// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately.
46pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 {
52pub fn fma_f64(x: f64, y: f64, z: f64) f64 {
4753 if (!math.isFinite(x) or !math.isFinite(y)) {
4854 return x * y + z;
4955 }
......@@ -90,11 +96,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 {
9096 }
9197}
9298
93pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 {
99fn __fmax(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi, c: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
100 return compiler_rt.f80.toAbi(fma_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b), compiler_rt.f80.fromAbi(c)));
101}
102pub fn fma_f80(a: f80, b: f80, c: f80) f80 {
94103 // TODO: more efficient implementation
95 return @floatCast(fmaq(a, b, c));
104 return @floatCast(fma_f128(a, b, c));
96105}
97106
107fn fmaq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi, z: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
108 return compiler_rt.f128.toAbi(fma_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y), compiler_rt.f128.fromAbi(z)));
109}
98110/// Fused multiply-add: Compute x * y + z with a single rounding error.
99111///
100112/// We use scaling to avoid overflow/underflow, along with the
......@@ -102,7 +114,7 @@ pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 {
102114///
103115/// Dekker, T. A Floating-Point Technique for Extending the
104116/// Available Precision. Numer. Math. 18, 224-242 (1971).
105pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 {
117pub fn fma_f128(x: f128, y: f128, z: f128) f128 {
106118 if (!math.isFinite(x) or !math.isFinite(y)) {
107119 return x * y + z;
108120 }
......@@ -151,10 +163,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 {
151163
152164pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble {
153165 switch (@typeInfo(c_longdouble).float.bits) {
154 64 => return fma(x, y, z),
155 80 => return __fmax(x, y, z),
156 128 => return fmaq(x, y, z),
157 else => @compileError("unreachable"),
166 64 => return fma_f64(x, y, z),
167 80 => return fma_f80(x, y, z),
168 128 => return fma_f128(x, y, z),
169 else => comptime unreachable,
158170 }
159171}
160172
......@@ -316,35 +328,35 @@ fn dd_mul128(a: f128, b: f128) dd128 {
316328test "32" {
317329 const epsilon = 0.000001;
318330
319 try expect(math.approxEqAbs(f32, fmaf(0.0, 5.0, 9.124), 9.124, epsilon));
320 try expect(math.approxEqAbs(f32, fmaf(0.2, 5.0, 9.124), 10.124, epsilon));
321 try expect(math.approxEqAbs(f32, fmaf(0.8923, 5.0, 9.124), 13.5855, epsilon));
322 try expect(math.approxEqAbs(f32, fmaf(1.5, 5.0, 9.124), 16.624, epsilon));
323 try expect(math.approxEqAbs(f32, fmaf(37.45, 5.0, 9.124), 196.374004, epsilon));
324 try expect(math.approxEqAbs(f32, fmaf(89.123, 5.0, 9.124), 454.739005, epsilon));
325 try expect(math.approxEqAbs(f32, fmaf(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
331 try expect(math.approxEqAbs(f32, fma_f32(0.0, 5.0, 9.124), 9.124, epsilon));
332 try expect(math.approxEqAbs(f32, fma_f32(0.2, 5.0, 9.124), 10.124, epsilon));
333 try expect(math.approxEqAbs(f32, fma_f32(0.8923, 5.0, 9.124), 13.5855, epsilon));
334 try expect(math.approxEqAbs(f32, fma_f32(1.5, 5.0, 9.124), 16.624, epsilon));
335 try expect(math.approxEqAbs(f32, fma_f32(37.45, 5.0, 9.124), 196.374004, epsilon));
336 try expect(math.approxEqAbs(f32, fma_f32(89.123, 5.0, 9.124), 454.739005, epsilon));
337 try expect(math.approxEqAbs(f32, fma_f32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
326338}
327339
328340test "64" {
329341 const epsilon = 0.000001;
330342
331 try expect(math.approxEqAbs(f64, fma(0.0, 5.0, 9.124), 9.124, epsilon));
332 try expect(math.approxEqAbs(f64, fma(0.2, 5.0, 9.124), 10.124, epsilon));
333 try expect(math.approxEqAbs(f64, fma(0.8923, 5.0, 9.124), 13.5855, epsilon));
334 try expect(math.approxEqAbs(f64, fma(1.5, 5.0, 9.124), 16.624, epsilon));
335 try expect(math.approxEqAbs(f64, fma(37.45, 5.0, 9.124), 196.374, epsilon));
336 try expect(math.approxEqAbs(f64, fma(89.123, 5.0, 9.124), 454.739, epsilon));
337 try expect(math.approxEqAbs(f64, fma(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
343 try expect(math.approxEqAbs(f64, fma_f64(0.0, 5.0, 9.124), 9.124, epsilon));
344 try expect(math.approxEqAbs(f64, fma_f64(0.2, 5.0, 9.124), 10.124, epsilon));
345 try expect(math.approxEqAbs(f64, fma_f64(0.8923, 5.0, 9.124), 13.5855, epsilon));
346 try expect(math.approxEqAbs(f64, fma_f64(1.5, 5.0, 9.124), 16.624, epsilon));
347 try expect(math.approxEqAbs(f64, fma_f64(37.45, 5.0, 9.124), 196.374, epsilon));
348 try expect(math.approxEqAbs(f64, fma_f64(89.123, 5.0, 9.124), 454.739, epsilon));
349 try expect(math.approxEqAbs(f64, fma_f64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
338350}
339351
340352test "128" {
341353 const epsilon = 0.000001;
342354
343 try expect(math.approxEqAbs(f128, fmaq(0.0, 5.0, 9.124), 9.124, epsilon));
344 try expect(math.approxEqAbs(f128, fmaq(0.2, 5.0, 9.124), 10.124, epsilon));
345 try expect(math.approxEqAbs(f128, fmaq(0.8923, 5.0, 9.124), 13.5855, epsilon));
346 try expect(math.approxEqAbs(f128, fmaq(1.5, 5.0, 9.124), 16.624, epsilon));
347 try expect(math.approxEqAbs(f128, fmaq(37.45, 5.0, 9.124), 196.374, epsilon));
348 try expect(math.approxEqAbs(f128, fmaq(89.123, 5.0, 9.124), 454.739, epsilon));
349 try expect(math.approxEqAbs(f128, fmaq(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
355 try expect(math.approxEqAbs(f128, fma_f128(0.0, 5.0, 9.124), 9.124, epsilon));
356 try expect(math.approxEqAbs(f128, fma_f128(0.2, 5.0, 9.124), 10.124, epsilon));
357 try expect(math.approxEqAbs(f128, fma_f128(0.8923, 5.0, 9.124), 13.5855, epsilon));
358 try expect(math.approxEqAbs(f128, fma_f128(1.5, 5.0, 9.124), 16.624, epsilon));
359 try expect(math.approxEqAbs(f128, fma_f128(37.45, 5.0, 9.124), 196.374, epsilon));
360 try expect(math.approxEqAbs(f128, fma_f128(89.123, 5.0, 9.124), 454.739, epsilon));
361 try expect(math.approxEqAbs(f128, fma_f128(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
350362}
lib/compiler_rt/fmax.zig+25-13
......@@ -10,39 +10,51 @@ comptime {
1010 symbol(&fmaxf, "fmaxf");
1111 symbol(&fmax, "fmax");
1212 symbol(&__fmaxx, "__fmaxx");
13 if (compiler_rt.want_ppc_abi) {
14 symbol(&fmaxq, "fmaxf128");
15 }
16 symbol(&fmaxq, "fmaxq");
13 symbol(&fmaxq, "fmaxf128");
1714 symbol(&fmaxl, "fmaxl");
1815}
1916
20pub fn __fmaxh(x: f16, y: f16) callconv(.c) f16 {
17fn __fmaxh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
18 return compiler_rt.f16.toAbi(fmax_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y)));
19}
20pub fn fmax_f16(x: f16, y: f16) f16 {
2121 return generic_fmax(f16, x, y);
2222}
2323
24pub fn fmaxf(x: f32, y: f32) callconv(.c) f32 {
24fn fmaxf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
25 return compiler_rt.f32.toAbi(fmax_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y)));
26}
27pub fn fmax_f32(x: f32, y: f32) f32 {
2528 return generic_fmax(f32, x, y);
2629}
2730
28pub fn fmax(x: f64, y: f64) callconv(.c) f64 {
31fn fmax(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
32 return compiler_rt.f64.toAbi(fmax_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y)));
33}
34pub fn fmax_f64(x: f64, y: f64) f64 {
2935 return generic_fmax(f64, x, y);
3036}
3137
32pub fn __fmaxx(x: f80, y: f80) callconv(.c) f80 {
38fn __fmaxx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
39 return compiler_rt.f80.toAbi(fmax_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y)));
40}
41pub fn fmax_f80(x: f80, y: f80) f80 {
3342 return generic_fmax(f80, x, y);
3443}
3544
36pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 {
45fn fmaxq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
46 return compiler_rt.f128.toAbi(fmax_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y)));
47}
48pub fn fmax_f128(x: f128, y: f128) f128 {
3749 return generic_fmax(f128, x, y);
3850}
3951
4052pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
4153 switch (@typeInfo(c_longdouble).float.bits) {
42 64 => return fmax(x, y),
43 80 => return __fmaxx(x, y),
44 128 => return fmaxq(x, y),
45 else => @compileError("unreachable"),
54 64 => return fmax_f64(x, y),
55 80 => return fmax_f80(x, y),
56 128 => return fmax_f128(x, y),
57 else => comptime unreachable,
4658 }
4759}
4860
lib/compiler_rt/fmin.zig+25-13
......@@ -10,39 +10,51 @@ comptime {
1010 symbol(&fminf, "fminf");
1111 symbol(&fmin, "fmin");
1212 symbol(&__fminx, "__fminx");
13 if (compiler_rt.want_ppc_abi) {
14 symbol(&fminq, "fminf128");
15 }
16 symbol(&fminq, "fminq");
13 symbol(&fminq, "fminf128");
1714 symbol(&fminl, "fminl");
1815}
1916
20pub fn __fminh(x: f16, y: f16) callconv(.c) f16 {
17fn __fminh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
18 return compiler_rt.f16.toAbi(fmin_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y)));
19}
20pub fn fmin_f16(x: f16, y: f16) f16 {
2121 return generic_fmin(f16, x, y);
2222}
2323
24pub fn fminf(x: f32, y: f32) callconv(.c) f32 {
24fn fminf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
25 return compiler_rt.f32.toAbi(fmin_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y)));
26}
27pub fn fmin_f32(x: f32, y: f32) f32 {
2528 return generic_fmin(f32, x, y);
2629}
2730
28pub fn fmin(x: f64, y: f64) callconv(.c) f64 {
31fn fmin(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
32 return compiler_rt.f64.toAbi(fmin_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y)));
33}
34pub fn fmin_f64(x: f64, y: f64) f64 {
2935 return generic_fmin(f64, x, y);
3036}
3137
32pub fn __fminx(x: f80, y: f80) callconv(.c) f80 {
38fn __fminx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
39 return compiler_rt.f80.toAbi(fmin_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y)));
40}
41pub fn fmin_f80(x: f80, y: f80) f80 {
3342 return generic_fmin(f80, x, y);
3443}
3544
36pub fn fminq(x: f128, y: f128) callconv(.c) f128 {
45fn fminq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
46 return compiler_rt.f128.toAbi(fmin_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y)));
47}
48pub fn fmin_f128(x: f128, y: f128) f128 {
3749 return generic_fmin(f128, x, y);
3850}
3951
4052pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
4153 switch (@typeInfo(c_longdouble).float.bits) {
42 64 => return fmin(x, y),
43 80 => return __fminx(x, y),
44 128 => return fminq(x, y),
45 else => @compileError("unreachable"),
54 64 => return fmin_f64(x, y),
55 80 => return fmin_f80(x, y),
56 128 => return fmin_f128(x, y),
57 else => comptime unreachable,
4658 }
4759}
4860
lib/compiler_rt/fmod.zig+50-38
......@@ -12,29 +12,38 @@ comptime {
1212 symbol(&fmodf, "fmodf");
1313 symbol(&fmod, "fmod");
1414 symbol(&__fmodx, "__fmodx");
15 if (compiler_rt.want_ppc_abi) {
16 symbol(&fmodq, "fmodf128");
17 }
18 symbol(&fmodq, "fmodq");
15 symbol(&fmodq, "fmodf128");
1916 symbol(&fmodl, "fmodl");
2017}
2118
22pub fn __fmodh(x: f16, y: f16) callconv(.c) f16 {
19fn __fmodh(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
20 return compiler_rt.f16.toAbi(fmod_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
21}
22pub fn fmod_f16(x: f16, y: f16) f16 {
2323 // TODO: more efficient implementation
24 return @floatCast(fmodf(x, y));
24 return @floatCast(fmod_f32(x, y));
2525}
2626
27pub fn fmodf(x: f32, y: f32) callconv(.c) f32 {
27fn fmodf(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
28 return compiler_rt.f32.toAbi(fmod_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
29}
30pub fn fmod_f32(x: f32, y: f32) f32 {
2831 return generic_fmod(f32, x, y);
2932}
3033
31pub fn fmod(x: f64, y: f64) callconv(.c) f64 {
34fn fmod(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
35 return compiler_rt.f64.toAbi(fmod_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
36}
37pub fn fmod_f64(x: f64, y: f64) f64 {
3238 return generic_fmod(f64, x, y);
3339}
3440
41fn __fmodx(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
42 return compiler_rt.f80.toAbi(fmod_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
43}
3544/// fmodx - floating modulo large, returns the remainder of division for f80 types
3645/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits
37pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 {
46pub fn fmod_f80(a: f80, b: f80) f80 {
3847 const T = f80;
3948 const Z = @Int(.unsigned, @bitSizeOf(T));
4049
......@@ -130,9 +139,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 {
130139 }
131140}
132141
142fn fmodq(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
143 return compiler_rt.f128.toAbi(fmod_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
144}
133145/// fmodq - floating modulo large, returns the remainder of division for f128 types
134146/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits
135pub fn fmodq(a: f128, b: f128) callconv(.c) f128 {
147pub fn fmod_f128(a: f128, b: f128) f128 {
136148 var amod = a;
137149 var bmod = b;
138150 const aPtr_u64: [*]u64 = @ptrCast(&amod);
......@@ -251,10 +263,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 {
251263
252264pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble {
253265 switch (@typeInfo(c_longdouble).float.bits) {
254 64 => return fmod(a, b),
255 80 => return __fmodx(a, b),
256 128 => return fmodq(a, b),
257 else => @compileError("unreachable"),
266 64 => return fmod_f64(a, b),
267 80 => return fmod_f80(a, b),
268 128 => return fmod_f128(a, b),
269 else => comptime unreachable,
258270 }
259271}
260272
......@@ -342,42 +354,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
342354 return @bitCast(ux);
343355}
344356
345test "fmodf" {
357test fmod_f32 {
346358 const nan_val = math.nan(f32);
347359 const inf_val = math.inf(f32);
348360
349 try std.testing.expect(math.isNan(fmodf(nan_val, 1.0)));
350 try std.testing.expect(math.isNan(fmodf(1.0, nan_val)));
351 try std.testing.expect(math.isNan(fmodf(inf_val, 1.0)));
352 try std.testing.expect(math.isNan(fmodf(0.0, 0.0)));
353 try std.testing.expect(math.isNan(fmodf(1.0, 0.0)));
361 try std.testing.expect(math.isNan(fmod_f32(nan_val, 1.0)));
362 try std.testing.expect(math.isNan(fmod_f32(1.0, nan_val)));
363 try std.testing.expect(math.isNan(fmod_f32(inf_val, 1.0)));
364 try std.testing.expect(math.isNan(fmod_f32(0.0, 0.0)));
365 try std.testing.expect(math.isNan(fmod_f32(1.0, 0.0)));
354366
355 try std.testing.expectEqual(@as(f32, 0.0), fmodf(0.0, 2.0));
356 try std.testing.expectEqual(@as(f32, -0.0), fmodf(-0.0, 2.0));
367 try std.testing.expectEqual(@as(f32, 0.0), fmod_f32(0.0, 2.0));
368 try std.testing.expectEqual(@as(f32, -0.0), fmod_f32(-0.0, 2.0));
357369
358 try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, 10.0));
359 try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, -10.0));
360 try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, 10.0));
361 try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, -10.0));
370 try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, 10.0));
371 try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, -10.0));
372 try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, 10.0));
373 try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, -10.0));
362374}
363375
364test "fmod" {
376test fmod_f64 {
365377 const nan_val = math.nan(f64);
366378 const inf_val = math.inf(f64);
367379
368 try std.testing.expect(math.isNan(fmod(nan_val, 1.0)));
369 try std.testing.expect(math.isNan(fmod(1.0, nan_val)));
370 try std.testing.expect(math.isNan(fmod(inf_val, 1.0)));
371 try std.testing.expect(math.isNan(fmod(0.0, 0.0)));
372 try std.testing.expect(math.isNan(fmod(1.0, 0.0)));
380 try std.testing.expect(math.isNan(fmod_f64(nan_val, 1.0)));
381 try std.testing.expect(math.isNan(fmod_f64(1.0, nan_val)));
382 try std.testing.expect(math.isNan(fmod_f64(inf_val, 1.0)));
383 try std.testing.expect(math.isNan(fmod_f64(0.0, 0.0)));
384 try std.testing.expect(math.isNan(fmod_f64(1.0, 0.0)));
373385
374 try std.testing.expectEqual(@as(f64, 0.0), fmod(0.0, 2.0));
375 try std.testing.expectEqual(@as(f64, -0.0), fmod(-0.0, 2.0));
386 try std.testing.expectEqual(@as(f64, 0.0), fmod_f64(0.0, 2.0));
387 try std.testing.expectEqual(@as(f64, -0.0), fmod_f64(-0.0, 2.0));
376388
377 try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, 10.0));
378 try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, -10.0));
379 try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, 10.0));
380 try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, -10.0));
389 try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, 10.0));
390 try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, -10.0));
391 try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, 10.0));
392 try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, -10.0));
381393}
382394
383395test {
lib/compiler_rt/fmodq_test.zig+32-32
......@@ -1,52 +1,52 @@
11const std = @import("std");
2const fmod = @import("fmod.zig");
2const fmod_f128 = @import("fmod.zig").fmod_f128;
33const testing = std.testing;
44
5fn test_fmodq(a: f128, b: f128, exp: f128) !void {
6 const res = fmod.fmodq(a, b);
5fn test_fmod_f128(a: f128, b: f128, exp: f128) !void {
6 const res = fmod_f128(a, b);
77 try testing.expect(exp == res);
88}
99
10fn test_fmodq_nans() !void {
11 try testing.expect(std.math.isNan(fmod.fmodq(1.0, std.math.nan(f128))));
12 try testing.expect(std.math.isNan(fmod.fmodq(1.0, -std.math.nan(f128))));
13 try testing.expect(std.math.isNan(fmod.fmodq(std.math.nan(f128), 1.0)));
14 try testing.expect(std.math.isNan(fmod.fmodq(-std.math.nan(f128), 1.0)));
10fn test_fmod_f128_nans() !void {
11 try testing.expect(std.math.isNan(fmod_f128(1.0, std.math.nan(f128))));
12 try testing.expect(std.math.isNan(fmod_f128(1.0, -std.math.nan(f128))));
13 try testing.expect(std.math.isNan(fmod_f128(std.math.nan(f128), 1.0)));
14 try testing.expect(std.math.isNan(fmod_f128(-std.math.nan(f128), 1.0)));
1515}
1616
17fn test_fmodq_infs() !void {
18 try testing.expect(fmod.fmodq(1.0, std.math.inf(f128)) == 1.0);
19 try testing.expect(fmod.fmodq(1.0, -std.math.inf(f128)) == 1.0);
20 try testing.expect(std.math.isNan(fmod.fmodq(std.math.inf(f128), 1.0)));
21 try testing.expect(std.math.isNan(fmod.fmodq(-std.math.inf(f128), 1.0)));
17fn test_fmod_f128_infs() !void {
18 try testing.expect(fmod_f128(1.0, std.math.inf(f128)) == 1.0);
19 try testing.expect(fmod_f128(1.0, -std.math.inf(f128)) == 1.0);
20 try testing.expect(std.math.isNan(fmod_f128(std.math.inf(f128), 1.0)));
21 try testing.expect(std.math.isNan(fmod_f128(-std.math.inf(f128), 1.0)));
2222}
2323
24test "fmodq" {
25 try test_fmodq(6.8, 4.0, 2.8);
26 try test_fmodq(6.8, -4.0, 2.8);
27 try test_fmodq(-6.8, 4.0, -2.8);
28 try test_fmodq(-6.8, -4.0, -2.8);
29 try test_fmodq(3.0, 2.0, 1.0);
30 try test_fmodq(-5.0, 3.0, -2.0);
31 try test_fmodq(3.0, 2.0, 1.0);
32 try test_fmodq(1.0, 2.0, 1.0);
33 try test_fmodq(0.0, 1.0, 0.0);
34 try test_fmodq(-0.0, 1.0, -0.0);
35 try test_fmodq(7046119.0, 5558362.0, 1487757.0);
36 try test_fmodq(9010357.0, 1957236.0, 1181413.0);
37 try test_fmodq(5192296858534827628530496329220095, 10.0, 5.0);
38 try test_fmodq(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157);
24test fmod_f128 {
25 try test_fmod_f128(6.8, 4.0, 2.8);
26 try test_fmod_f128(6.8, -4.0, 2.8);
27 try test_fmod_f128(-6.8, 4.0, -2.8);
28 try test_fmod_f128(-6.8, -4.0, -2.8);
29 try test_fmod_f128(3.0, 2.0, 1.0);
30 try test_fmod_f128(-5.0, 3.0, -2.0);
31 try test_fmod_f128(3.0, 2.0, 1.0);
32 try test_fmod_f128(1.0, 2.0, 1.0);
33 try test_fmod_f128(0.0, 1.0, 0.0);
34 try test_fmod_f128(-0.0, 1.0, -0.0);
35 try test_fmod_f128(7046119.0, 5558362.0, 1487757.0);
36 try test_fmod_f128(9010357.0, 1957236.0, 1181413.0);
37 try test_fmod_f128(5192296858534827628530496329220095, 10.0, 5.0);
38 try test_fmod_f128(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157);
3939
4040 // Denormals
4141 const a1: f128 = 0xedcb34a235253948765432134674p-16494;
4242 const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494;
4343 const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494;
44 try test_fmodq(a1, b1, exp1);
44 try test_fmod_f128(a1, b1, exp1);
4545 const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382;
4646 const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382;
4747 const exp2: f128 = 0x0.0001_aecd_9d66_4a6e_67b7_d7d0_a901p-16382;
48 try test_fmodq(a2, b2, exp2);
48 try test_fmod_f128(a2, b2, exp2);
4949
50 try test_fmodq_nans();
51 try test_fmodq_infs();
50 try test_fmod_f128_nans();
51 try test_fmod_f128_infs();
5252}
lib/compiler_rt/fmodx_test.zig+31-31
......@@ -1,52 +1,52 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const fmod = @import("fmod.zig");
3const fmod_f80 = @import("fmod.zig").fmod_f80;
44const testing = std.testing;
55
6fn test_fmodx(a: f80, b: f80, exp: f80) !void {
7 const res = fmod.__fmodx(a, b);
6fn test_fmod_f80(a: f80, b: f80, exp: f80) !void {
7 const res = fmod_f80(a, b);
88 try testing.expect(exp == res);
99}
1010
11fn test_fmodx_nans() !void {
12 try testing.expect(std.math.isNan(fmod.__fmodx(1.0, std.math.nan(f80))));
13 try testing.expect(std.math.isNan(fmod.__fmodx(1.0, -std.math.nan(f80))));
14 try testing.expect(std.math.isNan(fmod.__fmodx(std.math.nan(f80), 1.0)));
15 try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.nan(f80), 1.0)));
11fn test_fmod_f80_nans() !void {
12 try testing.expect(std.math.isNan(fmod_f80(1.0, std.math.nan(f80))));
13 try testing.expect(std.math.isNan(fmod_f80(1.0, -std.math.nan(f80))));
14 try testing.expect(std.math.isNan(fmod_f80(std.math.nan(f80), 1.0)));
15 try testing.expect(std.math.isNan(fmod_f80(-std.math.nan(f80), 1.0)));
1616}
1717
18fn test_fmodx_infs() !void {
19 try testing.expect(fmod.__fmodx(1.0, std.math.inf(f80)) == 1.0);
20 try testing.expect(fmod.__fmodx(1.0, -std.math.inf(f80)) == 1.0);
21 try testing.expect(std.math.isNan(fmod.__fmodx(std.math.inf(f80), 1.0)));
22 try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.inf(f80), 1.0)));
18fn test_fmod_f80_infs() !void {
19 try testing.expect(fmod_f80(1.0, std.math.inf(f80)) == 1.0);
20 try testing.expect(fmod_f80(1.0, -std.math.inf(f80)) == 1.0);
21 try testing.expect(std.math.isNan(fmod_f80(std.math.inf(f80), 1.0)));
22 try testing.expect(std.math.isNan(fmod_f80(-std.math.inf(f80), 1.0)));
2323}
2424
25test "fmodx" {
26 try test_fmodx(6.4, 4.0, 2.4);
27 try test_fmodx(6.4, -4.0, 2.4);
28 try test_fmodx(-6.4, 4.0, -2.4);
29 try test_fmodx(-6.4, -4.0, -2.4);
30 try test_fmodx(3.0, 2.0, 1.0);
31 try test_fmodx(-5.0, 3.0, -2.0);
32 try test_fmodx(3.0, 2.0, 1.0);
33 try test_fmodx(1.0, 2.0, 1.0);
34 try test_fmodx(0.0, 1.0, 0.0);
35 try test_fmodx(-0.0, 1.0, -0.0);
36 try test_fmodx(7046119.0, 5558362.0, 1487757.0);
37 try test_fmodx(9010357.0, 1957236.0, 1181413.0);
38 try test_fmodx(9223372036854775807, 10.0, 7.0);
25test fmod_f80 {
26 try test_fmod_f80(6.4, 4.0, 2.4);
27 try test_fmod_f80(6.4, -4.0, 2.4);
28 try test_fmod_f80(-6.4, 4.0, -2.4);
29 try test_fmod_f80(-6.4, -4.0, -2.4);
30 try test_fmod_f80(3.0, 2.0, 1.0);
31 try test_fmod_f80(-5.0, 3.0, -2.0);
32 try test_fmod_f80(3.0, 2.0, 1.0);
33 try test_fmod_f80(1.0, 2.0, 1.0);
34 try test_fmod_f80(0.0, 1.0, 0.0);
35 try test_fmod_f80(-0.0, 1.0, -0.0);
36 try test_fmod_f80(7046119.0, 5558362.0, 1487757.0);
37 try test_fmod_f80(9010357.0, 1957236.0, 1181413.0);
38 try test_fmod_f80(9223372036854775807, 10.0, 7.0);
3939
4040 // Denormals
4141 const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;
4242 const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381;
4343 const exp1: f80 = 0x0.19b7_61d7_fd96_dc30p-16381;
44 try test_fmodx(a1, b1, exp1);
44 try test_fmod_f80(a1, b1, exp1);
4545 const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381;
4646 const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381;
4747 const exp2: f80 = 0x0.022c_b86c_a6a3_9ad4p-16381;
48 try test_fmodx(a2, b2, exp2);
48 try test_fmod_f80(a2, b2, exp2);
4949
50 try test_fmodx_nans();
51 try test_fmodx_infs();
50 try test_fmod_f80_nans();
51 try test_fmod_f80_infs();
5252}
lib/compiler_rt/gedf2.zig deleted-35
......@@ -1,35 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const comparef = @import("./comparef.zig");
5const symbol = @import("../compiler_rt.zig").symbol;
6
7comptime {
8 if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_dcmpge, "__aeabi_dcmpge");
10 symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt");
11 } else {
12 symbol(&__gedf2, "__gedf2");
13 symbol(&__gtdf2, "__gtdf2");
14 }
15}
16
17/// "These functions return a value greater than or equal to zero if neither
18/// argument is NaN, and a is greater than or equal to b."
19pub fn __gedf2(a: f64, b: f64) callconv(.c) i32 {
20 return @backingInt(comparef.cmpf2(f64, comparef.GE, a, b));
21}
22
23/// "These functions return a value greater than zero if neither argument is NaN,
24/// and a is strictly greater than b."
25pub fn __gtdf2(a: f64, b: f64) callconv(.c) i32 {
26 return __gedf2(a, b);
27}
28
29fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
30 return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) != .Less);
31}
32
33fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
34 return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) == .Greater);
35}
lib/compiler_rt/gehf2.zig deleted-21
......@@ -1,21 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const symbol = @import("../compiler_rt.zig").symbol;
4const comparef = @import("./comparef.zig");
5
6comptime {
7 symbol(&__gehf2, "__gehf2");
8 symbol(&__gthf2, "__gthf2");
9}
10
11/// "These functions return a value greater than or equal to zero if neither
12/// argument is NaN, and a is greater than or equal to b."
13pub fn __gehf2(a: f16, b: f16) callconv(.c) i32 {
14 return @backingInt(comparef.cmpf2(f16, comparef.GE, a, b));
15}
16
17/// "These functions return a value greater than zero if neither argument is NaN,
18/// and a is strictly greater than b."
19pub fn __gthf2(a: f16, b: f16) callconv(.c) i32 {
20 return __gehf2(a, b);
21}
lib/compiler_rt/gesf2.zig deleted-35
......@@ -1,35 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const comparef = @import("./comparef.zig");
6
7comptime {
8 if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_fcmpge, "__aeabi_fcmpge");
10 symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt");
11 } else {
12 symbol(&__gesf2, "__gesf2");
13 symbol(&__gtsf2, "__gtsf2");
14 }
15}
16
17/// "These functions return a value greater than or equal to zero if neither
18/// argument is NaN, and a is greater than or equal to b."
19pub fn __gesf2(a: f32, b: f32) callconv(.c) i32 {
20 return @backingInt(comparef.cmpf2(f32, comparef.GE, a, b));
21}
22
23/// "These functions return a value greater than zero if neither argument is NaN,
24/// and a is strictly greater than b."
25pub fn __gtsf2(a: f32, b: f32) callconv(.c) i32 {
26 return __gesf2(a, b);
27}
28
29fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
30 return @intFromBool(comparef.cmpf2(f32, comparef.GE, a, b) != .Less);
31}
32
33fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
34 return @intFromBool(comparef.cmpf2(f32, comparef.LE, a, b) == .Greater);
35}
lib/compiler_rt/getf2.zig deleted-26
......@@ -1,26 +0,0 @@
1///! The quoted behavior definitions are from
2///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5const comparef = @import("./comparef.zig");
6
7comptime {
8 if (compiler_rt.want_ppc_abi) {
9 symbol(&__getf2, "__gekf2");
10 symbol(&__gttf2, "__gtkf2");
11 }
12 symbol(&__getf2, "__getf2");
13 symbol(&__gttf2, "__gttf2");
14}
15
16/// "These functions return a value greater than or equal to zero if neither
17/// argument is NaN, and a is greater than or equal to b."
18fn __getf2(a: f128, b: f128) callconv(.c) i32 {
19 return @backingInt(comparef.cmpf2(f128, comparef.GE, a, b));
20}
21
22/// "These functions return a value greater than zero if neither argument is NaN,
23/// and a is strictly greater than b."
24fn __gttf2(a: f128, b: f128) callconv(.c) i32 {
25 return __getf2(a, b);
26}
lib/compiler_rt/gexf2.zig deleted-15
......@@ -1,15 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const comparef = @import("./comparef.zig");
3
4comptime {
5 symbol(&__gexf2, "__gexf2");
6 symbol(&__gtxf2, "__gtxf2");
7}
8
9fn __gexf2(a: f80, b: f80) callconv(.c) i32 {
10 return @backingInt(comparef.cmp_f80(comparef.GE, a, b));
11}
12
13fn __gtxf2(a: f80, b: f80) callconv(.c) i32 {
14 return __gexf2(a, b);
15}
lib/compiler_rt/int.zig+39-40
......@@ -36,7 +36,7 @@ comptime {
3636
3737pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 {
3838 const d = __divti3(a, b);
39 rem.* = a -% (d * b);
39 rem.* = a - d *% b;
4040 return d;
4141}
4242
......@@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi
6969
7070pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 {
7171 const d = __divdi3(a, b);
72 rem.* = a -% (d * b);
72 rem.* = a - d *% b;
7373 return d;
7474}
7575
......@@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
7979 try testing.expect(q == expected_q and r == expected_r);
8080}
8181
82const cases__divmoddi4 =
83 [_][4]i64{
84 [_]i64{ 0, 1, 0, 0 },
85 [_]i64{ 0, -1, 0, 0 },
86 [_]i64{ 2, 1, 2, 0 },
87 [_]i64{ 2, -1, -2, 0 },
88 [_]i64{ -2, 1, -2, 0 },
89 [_]i64{ -2, -1, 2, 0 },
90 [_]i64{ 7, 5, 1, 2 },
91 [_]i64{ -7, 5, -1, -2 },
92 [_]i64{ 19, 5, 3, 4 },
93 [_]i64{ 19, -5, -3, 4 },
94 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 },
95 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },
96 };
82const cases__divmoddi4 = [_][4]i64{
83 [_]i64{ 0, 1, 0, 0 },
84 [_]i64{ 0, -1, 0, 0 },
85 [_]i64{ 2, 1, 2, 0 },
86 [_]i64{ 2, -1, -2, 0 },
87 [_]i64{ -2, 1, -2, 0 },
88 [_]i64{ -2, -1, 2, 0 },
89 [_]i64{ 7, 5, 1, 2 },
90 [_]i64{ -7, 5, -1, -2 },
91 [_]i64{ 19, 5, 3, 4 },
92 [_]i64{ 19, -5, -3, 4 },
93 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 },
94 [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },
95};
9796
9897test "test_divmoddi4" {
9998 for (cases__divmoddi4) |case| {
......@@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 {
105104 return udivmod(u64, a, b, maybe_rem);
106105}
107106
108test "test_udivmoddi4" {
109 _ = @import("udivmoddi4_test.zig");
110}
111
112107pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 {
113108 // Set aside the sign of the quotient.
114109 const sign: u64 = @bitCast((a ^ b) >> 63);
......@@ -209,25 +204,24 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void {
209204
210205pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 {
211206 const d = __divsi3(a, b);
212 rem.* = a -% (d * b);
207 rem.* = a - d *% b;
213208 return d;
214209}
215210
216const cases__divmodsi4 =
217 [_][4]i32{
218 [_]i32{ 0, 1, 0, 0 },
219 [_]i32{ 0, -1, 0, 0 },
220 [_]i32{ 2, 1, 2, 0 },
221 [_]i32{ 2, -1, -2, 0 },
222 [_]i32{ -2, 1, -2, 0 },
223 [_]i32{ -2, -1, 2, 0 },
224 [_]i32{ 7, 5, 1, 2 },
225 [_]i32{ -7, 5, -1, -2 },
226 [_]i32{ 19, 5, 3, 4 },
227 [_]i32{ 19, -5, -3, 4 },
228 [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },
229 [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },
230 };
211const cases__divmodsi4 = [_][4]i32{
212 [_]i32{ 0, 1, 0, 0 },
213 [_]i32{ 0, -1, 0, 0 },
214 [_]i32{ 2, 1, 2, 0 },
215 [_]i32{ 2, -1, -2, 0 },
216 [_]i32{ -2, 1, -2, 0 },
217 [_]i32{ -2, -1, 2, 0 },
218 [_]i32{ 7, 5, 1, 2 },
219 [_]i32{ -7, 5, -1, -2 },
220 [_]i32{ 19, 5, 3, 4 },
221 [_]i32{ 19, -5, -3, 4 },
222 [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },
223 [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },
224};
231225
232226fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
233227 var r: i32 = undefined;
......@@ -243,7 +237,7 @@ test "test_divmodsi4" {
243237
244238pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 {
245239 const d = __udivsi3(a, b);
246 rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b))));
240 rem.* = a - d * b;
247241 return d;
248242}
249243
......@@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {
486480}
487481
488482pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 {
489 return n -% __divsi3(n, d) * d;
483 return n - __divsi3(n, d) *% d;
490484}
491485
492486test "test_modsi3" {
......@@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {
515509}
516510
517511pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 {
518 return n -% __udivsi3(n, d) * d;
512 return n - __udivsi3(n, d) * d;
519513}
520514
521515test "test_umodsi3" {
......@@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {
663657 const r: u32 = __umodsi3(a, b);
664658 try testing.expect(r == expected_r);
665659}
660
661test {
662 _ = @import("udivmodsi4_test.zig");
663 _ = @import("udivmoddi4_test.zig");
664}
lib/compiler_rt/int_from_float.zig+513-9
......@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
12const std = @import("std");
23const math = std.math;
34const Log2Int = std.math.Log2Int;
......@@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig");
67const symbol = compiler_rt.symbol;
78
89comptime {
9 symbol(&__fixxfti, "__fixxfti");
1010 symbol(&__fixhfsi, "__fixhfsi");
1111 symbol(&__fixhfdi, "__fixhfdi");
1212 symbol(&__fixhfti, "__fixhfti");
13 symbol(&__fixhfei, "__fixhfei");
14
15 if (compiler_rt.want_aeabi) {
16 symbol(&__aeabi_f2iz, "__aeabi_f2iz");
17 symbol(&__aeabi_f2lz, "__aeabi_f2lz");
18 symbol(&__aeabi_fixsfti, "__fixsfti");
19 } else {
20 symbol(&__fixsfsi, "__fixsfsi");
21 symbol(&__fixsfdi, "__fixsfdi");
22 if (compiler_rt.want_windows_arm_abi) symbol(&__fixsfdi, "__stoi64");
23 symbol(&__fixsfti, "__fixsfti");
24 }
25 symbol(&__fixsfei, "__fixsfei");
26
27 if (compiler_rt.want_aeabi) {
28 symbol(&__aeabi_d2iz, "__aeabi_d2iz");
29 symbol(&__aeabi_d2lz, "__aeabi_d2lz");
30 symbol(&__aeabi_fixdfti, "__fixdfti");
31 } else {
32 symbol(&__fixdfsi, "__fixdfsi");
33 symbol(&__fixdfdi, "__fixdfdi");
34 if (compiler_rt.want_windows_arm_abi) symbol(&__fixdfdi, "__dtoi64");
35 symbol(&__fixdfti, "__fixdfti");
36 }
37 symbol(&__fixdfei, "__fixdfei");
38
39 symbol(&__fixxfsi, "__fixxfsi");
40 symbol(&__fixxfdi, "__fixxfdi");
41 symbol(&__fixxfti, "__fixxfti");
42 symbol(&__fixxfei, "__fixxfei");
43
44 if (compiler_rt.want_ppc_abi) {
45 symbol(&__fixtfsi, "__fixkfsi");
46 symbol(&__fixtfdi, "__fixkfdi");
47 } else if (compiler_rt.want_sparc64_abi) {
48 symbol(&_Qp_qtoi, "_Qp_qtoi");
49 symbol(&_Qp_qtox, "_Qp_qtox");
50 } else if (compiler_rt.want_sparc32_abi) {
51 symbol(&__fixtfsi, "_Q_qtoi");
52 symbol(&__fixtfdi, "_Q_qtoll");
53 } else {
54 symbol(&__fixtfsi, "__fixtfsi");
55 symbol(&__fixtfdi, "__fixtfdi");
56 }
57 if (compiler_rt.want_ppc_abi) {
58 symbol(&__fixtfti, "__fixkfti");
59 symbol(&__fixtfei, "__fixkfei");
60 } else {
61 symbol(&__fixtfti, "__fixtfti");
62 symbol(&__fixtfei, "__fixtfei");
63 }
64}
65
66fn __fixhfsi(a: compiler_rt.f16.Abi) callconv(.c) i32 {
67 return i32_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
68}
69pub fn i32_intFromFloat_f16(a: f16) i32 {
70 return intFromFloat(i32, a);
71}
72
73fn __fixhfdi(a: compiler_rt.f16.Abi) callconv(.c) i64 {
74 return i64_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
75}
76pub fn i64_intFromFloat_f16(a: f16) i64 {
77 return intFromFloat(i64, a);
78}
79
80fn __fixhfti(a: compiler_rt.f16.Abi) callconv(.c) i128 {
81 return i128_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
82}
83pub fn i128_intFromFloat_f16(a: f16) i128 {
84 return intFromFloat(i128, a);
85}
86
87fn __fixhfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void {
88 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
89 return signed_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a));
90}
91pub fn signed_intFromFloat_f16(result: []u8, a: f16) void {
92 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
93}
94
95fn __fixsfsi(a: compiler_rt.f32.Abi) callconv(.c) i32 {
96 return i32_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
97}
98fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 {
99 return i32_intFromFloat_f32(a);
100}
101pub fn i32_intFromFloat_f32(a: f32) i32 {
102 return intFromFloat(i32, a);
103}
104
105fn __fixsfdi(a: compiler_rt.f32.Abi) callconv(.c) i64 {
106 return i64_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
107}
108fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 {
109 return i64_intFromFloat_f32(a);
110}
111pub fn i64_intFromFloat_f32(a: f32) i64 {
112 return intFromFloat(i64, a);
113}
114
115fn __fixsfti(a: compiler_rt.f32.Abi) callconv(.c) i128 {
116 return i128_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
117}
118fn __aeabi_fixsfti(_: compiler_rt.f32.Abi) callconv(.naked) i128 {
119 switch (builtin.abi.float()) {
120 .soft => asm volatile (
121 \\ push {r0-r4, lr}
122 \\ mov r1, r0
123 \\ mov r0, sp
124 \\ bl %[__fixsfti]
125 \\ pop {r0-r4, pc}
126 :
127 : [__fixsfti] "X" (&__fixsfti),
128 ),
129 .hard => asm volatile (
130 \\ push {r0-r4, lr}
131 \\ mov r0, sp
132 \\ bl %[__fixsfti]
133 \\ pop {r0-r4, pc}
134 :
135 : [__fixsfti] "X" (&__fixsfti),
136 ),
137 }
138}
139pub fn i128_intFromFloat_f32(a: f32) i128 {
140 return intFromFloat(i128, a);
141}
142
143fn __fixsfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void {
144 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
145 return signed_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a));
146}
147pub fn signed_intFromFloat_f32(result: []u8, a: f32) void {
148 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
149}
150
151fn __fixdfsi(a: compiler_rt.f64.Abi) callconv(.c) i32 {
152 return i32_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
153}
154fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
155 return i32_intFromFloat_f64(a);
156}
157pub fn i32_intFromFloat_f64(a: f64) i32 {
158 return intFromFloat(i32, a);
159}
160
161fn __fixdfdi(a: compiler_rt.f64.Abi) callconv(.c) i64 {
162 return i64_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
163}
164fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 {
165 return i64_intFromFloat_f64(a);
166}
167pub fn i64_intFromFloat_f64(a: f64) i64 {
168 return intFromFloat(i64, a);
13169}
14170
15pub fn __fixhfti(a: f16) callconv(.c) i128 {
171fn __fixdfti(a: compiler_rt.f64.Abi) callconv(.c) i128 {
172 return i128_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
173}
174fn __aeabi_fixdfti(_: compiler_rt.f64.Abi) callconv(.naked) i128 {
175 switch (builtin.abi.float()) {
176 .soft => asm volatile (
177 \\ push {r0-r4, lr}
178 \\ mov r3, r1
179 \\ mov r2, r0
180 \\ mov r0, sp
181 \\ bl %[__fixdfti]
182 \\ pop {r0-r4, pc}
183 :
184 : [__fixdfti] "X" (&__fixdfti),
185 ),
186 .hard => asm volatile (
187 \\ push {r0-r4, lr}
188 \\ mov r0, sp
189 \\ bl %[__fixdfti]
190 \\ pop {r0-r4, pc}
191 :
192 : [__fixdfti] "X" (&__fixdfti),
193 ),
194 }
195}
196pub fn i128_intFromFloat_f64(a: f64) i128 {
16197 return intFromFloat(i128, a);
17198}
18199
19fn __fixhfdi(a: f16) callconv(.c) i64 {
200fn __fixdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void {
201 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
202 return signed_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a));
203}
204pub fn signed_intFromFloat_f64(result: []u8, a: f64) void {
205 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
206}
207
208fn __fixxfsi(a: compiler_rt.f80.Abi) callconv(.c) i32 {
209 return i32_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
210}
211pub fn i32_intFromFloat_f80(a: f80) i32 {
212 return intFromFloat(i32, a);
213}
214
215fn __fixxfdi(a: compiler_rt.f80.Abi) callconv(.c) i64 {
216 return i64_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
217}
218pub fn i64_intFromFloat_f80(a: f80) i64 {
20219 return intFromFloat(i64, a);
21220}
22221
23fn __fixhfsi(a: f16) callconv(.c) i32 {
222fn __fixxfti(a: compiler_rt.f80.Abi) callconv(.c) i128 {
223 return i128_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
224}
225pub fn i128_intFromFloat_f80(a: f80) i128 {
226 return intFromFloat(i128, a);
227}
228
229fn __fixxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void {
230 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
231 return signed_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a));
232}
233pub fn signed_intFromFloat_f80(result: []u8, a: f80) void {
234 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
235}
236
237fn __fixtfsi(a: compiler_rt.f128.Abi) callconv(.c) i32 {
238 return i32_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
239}
240fn _Qp_qtoi(a: *const f128) callconv(.c) i32 {
241 return i32_intFromFloat_f128(a.*);
242}
243pub fn i32_intFromFloat_f128(a: f128) i32 {
24244 return intFromFloat(i32, a);
25245}
26246
27pub fn __fixxfti(a: f80) callconv(.c) i128 {
247fn __fixtfdi(a: compiler_rt.f128.Abi) callconv(.c) i64 {
248 return i64_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
249}
250fn _Qp_qtox(a: *const f128) callconv(.c) i64 {
251 return i64_intFromFloat_f128(a.*);
252}
253pub fn i64_intFromFloat_f128(a: f128) i64 {
254 return intFromFloat(i64, a);
255}
256
257fn __fixtfti(a: compiler_rt.f128.Abi) callconv(.c) i128 {
258 return i128_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
259}
260pub fn i128_intFromFloat_f128(a: f128) i128 {
28261 return intFromFloat(i128, a);
29262}
30263
31pub inline fn intFromFloat(comptime I: type, a: anytype) I {
264fn __fixtfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void {
265 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
266 return signed_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a));
267}
268pub fn signed_intFromFloat_f128(result: []u8, a: f128) void {
269 bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a);
270}
271
272comptime {
273 symbol(&__fixunshfsi, "__fixunshfsi");
274 symbol(&__fixunshfdi, "__fixunshfdi");
275 symbol(&__fixunshfti, "__fixunshfti");
276 symbol(&__fixunshfei, "__fixunshfei");
277
278 if (compiler_rt.want_aeabi) {
279 symbol(&__aeabi_f2uiz, "__aeabi_f2uiz");
280 symbol(&__aeabi_f2ulz, "__aeabi_f2ulz");
281 symbol(&__aeabi_fixunssfti, "__fixunssfti");
282 } else {
283 symbol(&__fixunssfsi, "__fixunssfsi");
284 symbol(&__fixunssfdi, "__fixunssfdi");
285 if (compiler_rt.want_windows_arm_abi) symbol(&__fixunssfdi, "__stou64");
286 symbol(&__fixunssfti, "__fixunssfti");
287 }
288 symbol(&__fixunssfei, "__fixunssfei");
289
290 if (compiler_rt.want_aeabi) {
291 symbol(&__aeabi_d2uiz, "__aeabi_d2uiz");
292 symbol(&__aeabi_d2ulz, "__aeabi_d2ulz");
293 symbol(&__aeabi_fixunsdfti, "__fixunsdfti");
294 } else {
295 symbol(&__fixunsdfsi, "__fixunsdfsi");
296 symbol(&__fixunsdfdi, "__fixunsdfdi");
297 if (compiler_rt.want_windows_arm_abi) symbol(&__fixunsdfdi, "__dtou64");
298 symbol(&__fixunsdfti, "__fixunsdfti");
299 }
300 symbol(&__fixunsdfei, "__fixunsdfei");
301
302 symbol(&__fixunsxfsi, "__fixunsxfsi");
303 symbol(&__fixunsxfdi, "__fixunsxfdi");
304 symbol(&__fixunsxfti, "__fixunsxfti");
305 symbol(&__fixunsxfei, "__fixunsxfei");
306
307 if (compiler_rt.want_ppc_abi) {
308 symbol(&__fixunstfsi, "__fixunskfsi");
309 symbol(&__fixunstfdi, "__fixunskfdi");
310 } else if (compiler_rt.want_sparc64_abi) {
311 symbol(&_Qp_qtoui, "_Qp_qtoui");
312 symbol(&_Qp_qtoux, "_Qp_qtoux");
313 } else if (compiler_rt.want_sparc32_abi) {
314 symbol(&__fixunstfsi, "_Q_qtou");
315 symbol(&__fixunstfdi, "_Q_qtoull");
316 } else {
317 symbol(&__fixunstfsi, "__fixunstfsi");
318 symbol(&__fixunstfdi, "__fixunstfdi");
319 }
320 if (compiler_rt.want_ppc_abi) {
321 symbol(&__fixunstfti, "__fixunskfti");
322 symbol(&__fixunstfei, "__fixunskfei");
323 } else {
324 symbol(&__fixunstfti, "__fixunstfti");
325 symbol(&__fixunstfei, "__fixunstfei");
326 }
327}
328
329fn __fixunshfsi(a: compiler_rt.f16.Abi) callconv(.c) u32 {
330 return u32_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
331}
332pub fn u32_intFromFloat_f16(a: f16) u32 {
333 return intFromFloat(u32, a);
334}
335
336fn __fixunshfdi(a: compiler_rt.f16.Abi) callconv(.c) u64 {
337 return u64_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
338}
339pub fn u64_intFromFloat_f16(a: f16) u64 {
340 return intFromFloat(u64, a);
341}
342
343fn __fixunshfti(a: compiler_rt.f16.Abi) callconv(.c) u128 {
344 return u128_intFromFloat_f16(compiler_rt.f16.fromAbi(a));
345}
346pub fn u128_intFromFloat_f16(a: f16) u128 {
347 return intFromFloat(u128, a);
348}
349
350fn __fixunshfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void {
351 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
352 return unsigned_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a));
353}
354pub fn unsigned_intFromFloat_f16(result: []u8, a: f16) void {
355 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
356}
357
358fn __fixunssfsi(a: compiler_rt.f32.Abi) callconv(.c) u32 {
359 return u32_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
360}
361fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 {
362 return u32_intFromFloat_f32(a);
363}
364pub fn u32_intFromFloat_f32(a: f32) u32 {
365 return intFromFloat(u32, a);
366}
367
368fn __fixunssfdi(a: compiler_rt.f32.Abi) callconv(.c) u64 {
369 return u64_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
370}
371fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 {
372 return u64_intFromFloat_f32(a);
373}
374pub fn u64_intFromFloat_f32(a: f32) u64 {
375 return intFromFloat(u64, a);
376}
377
378fn __fixunssfti(a: compiler_rt.f32.Abi) callconv(.c) u128 {
379 return u128_intFromFloat_f32(compiler_rt.f32.fromAbi(a));
380}
381fn __aeabi_fixunssfti(_: compiler_rt.f32.Abi) callconv(.naked) u128 {
382 switch (builtin.abi.float()) {
383 .soft => asm volatile (
384 \\ push {r0-r4, lr}
385 \\ mov r1, r0
386 \\ mov r0, sp
387 \\ bl %[__fixunssfti]
388 \\ pop {r0-r4, pc}
389 :
390 : [__fixunssfti] "X" (&__fixunssfti),
391 ),
392 .hard => asm volatile (
393 \\ push {r0-r4, lr}
394 \\ mov r0, sp
395 \\ bl %[__fixunssfti]
396 \\ pop {r0-r4, pc}
397 :
398 : [__fixunssfti] "X" (&__fixunssfti),
399 ),
400 }
401}
402pub fn u128_intFromFloat_f32(a: f32) u128 {
403 return intFromFloat(u128, a);
404}
405
406fn __fixunssfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void {
407 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
408 return unsigned_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a));
409}
410pub fn unsigned_intFromFloat_f32(result: []u8, a: f32) void {
411 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
412}
413
414fn __fixunsdfsi(a: compiler_rt.f64.Abi) callconv(.c) u32 {
415 return u32_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
416}
417fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 {
418 return u32_intFromFloat_f64(a);
419}
420pub fn u32_intFromFloat_f64(a: f64) u32 {
421 return intFromFloat(u32, a);
422}
423
424fn __fixunsdfdi(a: compiler_rt.f64.Abi) callconv(.c) u64 {
425 return u64_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
426}
427fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 {
428 return u64_intFromFloat_f64(a);
429}
430pub fn u64_intFromFloat_f64(a: f64) u64 {
431 return intFromFloat(u64, a);
432}
433
434fn __fixunsdfti(a: compiler_rt.f64.Abi) callconv(.c) u128 {
435 return u128_intFromFloat_f64(compiler_rt.f64.fromAbi(a));
436}
437fn __aeabi_fixunsdfti(_: compiler_rt.f64.Abi) callconv(.naked) u128 {
438 switch (builtin.abi.float()) {
439 .soft => asm volatile (
440 \\ push {r0-r4, lr}
441 \\ mov r3, r1
442 \\ mov r2, r0
443 \\ mov r0, sp
444 \\ bl %[__fixunsdfti]
445 \\ pop {r0-r4, pc}
446 :
447 : [__fixunsdfti] "X" (&__fixunsdfti),
448 ),
449 .hard => asm volatile (
450 \\ push {r0-r4, lr}
451 \\ mov r0, sp
452 \\ bl %[__fixunsdfti]
453 \\ pop {r0-r4, pc}
454 :
455 : [__fixunsdfti] "X" (&__fixunsdfti),
456 ),
457 }
458}
459pub fn u128_intFromFloat_f64(a: f64) u128 {
460 return intFromFloat(u128, a);
461}
462
463fn __fixunsdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void {
464 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
465 return unsigned_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a));
466}
467pub fn unsigned_intFromFloat_f64(result: []u8, a: f64) void {
468 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
469}
470
471fn __fixunsxfsi(a: compiler_rt.f80.Abi) callconv(.c) u32 {
472 return u32_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
473}
474pub fn u32_intFromFloat_f80(a: f80) u32 {
475 return intFromFloat(u32, a);
476}
477
478fn __fixunsxfdi(a: compiler_rt.f80.Abi) callconv(.c) u64 {
479 return u64_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
480}
481pub fn u64_intFromFloat_f80(a: f80) u64 {
482 return intFromFloat(u64, a);
483}
484
485fn __fixunsxfti(a: compiler_rt.f80.Abi) callconv(.c) u128 {
486 return u128_intFromFloat_f80(compiler_rt.f80.fromAbi(a));
487}
488pub fn u128_intFromFloat_f80(a: f80) u128 {
489 return intFromFloat(u128, a);
490}
491
492fn __fixunsxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void {
493 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
494 return unsigned_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a));
495}
496pub fn unsigned_intFromFloat_f80(result: []u8, a: f80) void {
497 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
498}
499
500fn __fixunstfsi(a: compiler_rt.f128.Abi) callconv(.c) u32 {
501 return u32_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
502}
503fn _Qp_qtoui(a: *const f128) callconv(.c) u32 {
504 return u32_intFromFloat_f128(a.*);
505}
506pub fn u32_intFromFloat_f128(a: f128) u32 {
507 return intFromFloat(u32, a);
508}
509
510fn __fixunstfdi(a: compiler_rt.f128.Abi) callconv(.c) u64 {
511 return u64_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
512}
513fn _Qp_qtoux(a: *const f128) callconv(.c) u64 {
514 return u64_intFromFloat_f128(a.*);
515}
516pub fn u64_intFromFloat_f128(a: f128) u64 {
517 return intFromFloat(u64, a);
518}
519
520fn __fixunstfti(a: compiler_rt.f128.Abi) callconv(.c) u128 {
521 return u128_intFromFloat_f128(compiler_rt.f128.fromAbi(a));
522}
523pub fn u128_intFromFloat_f128(a: f128) u128 {
524 return intFromFloat(u128, a);
525}
526
527fn __fixunstfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void {
528 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
529 return unsigned_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a));
530}
531pub fn unsigned_intFromFloat_f128(result: []u8, a: f128) void {
532 bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a);
533}
534
535inline fn intFromFloat(comptime I: type, a: anytype) I {
32536 const F = @TypeOf(a);
33537 const float_bits = @typeInfo(F).float.bits;
34538 const int_bits = @typeInfo(I).int.bits;
......@@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {
76580 return result;
77581}
78582
79pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, result: []u32, a: anytype) void {
583inline fn bigIntFromFloat(comptime signedness: std.lang.Signedness, result: []u32, a: anytype) void {
584 const endian = builtin.cpu.arch.endian();
80585 switch (result.len) {
81586 0 => return,
82587 inline 1...4 => |limbs_len| {
83588 const I = @Int(signedness, 32 * limbs_len);
84589 const low_to_high: [limbs_len]u32 = @bitCast(@as(I, @intFromFloat(a)));
85 result[0..limbs_len].* = switch (@import("builtin").cpu.arch.endian()) {
590 result[0..limbs_len].* = switch (endian) {
86591 .little => low_to_high,
87592 .big => switch (limbs_len) {
88593 1 => .{low_to_high[0]},
......@@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
111616 });
112617 switch (signedness) {
113618 .signed => {
114 const endian = @import("builtin").cpu.arch.endian();
115619 const exponent_limb = switch (endian) {
116620 .little => exponent / 32,
117621 .big => result.len - 1 - exponent / 32,
lib/compiler_rt/int_from_float_test.zig+913-897
......@@ -2,1023 +2,1039 @@ const std = @import("std");
22const testing = std.testing;
33const math = std.math;
44
5const __fixunshfti = @import("fixunshfti.zig").__fixunshfti;
6const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti;
7
8// Conversion from f32
9const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
10const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
11const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
12const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
13const __fixsfti = @import("fixsfti.zig").__fixsfti;
14const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
15const __fixsfei = @import("fixsfei.zig").__fixsfei;
16const __fixunssfei = @import("fixunssfei.zig").__fixunssfei;
17
18// Conversion from f64
19const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
20const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
21const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
22const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
23const __fixdfti = @import("fixdfti.zig").__fixdfti;
24const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
25const __fixdfei = @import("fixdfei.zig").__fixdfei;
26const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei;
27
28// Conversion from f128
29const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
30const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;
31const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
32const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
33const __fixtfti = @import("fixtfti.zig").__fixtfti;
34const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;
35
36fn test__fixsfsi(a: f32, expected: i32) !void {
37 const x = __fixsfsi(a);
5const impl = @import("int_from_float.zig");
6
7const i32_intFromFloat_f16 = impl.i32_intFromFloat_f16;
8const u32_intFromFloat_f16 = impl.u32_intFromFloat_f16;
9const i64_intFromFloat_f16 = impl.i64_intFromFloat_f16;
10const u64_intFromFloat_f16 = impl.u64_intFromFloat_f16;
11const i128_intFromFloat_f16 = impl.i128_intFromFloat_f16;
12const u128_intFromFloat_f16 = impl.u128_intFromFloat_f16;
13const signed_intFromFloat_f16 = impl.signed_intFromFloat_f16;
14const unsigned_intFromFloat_f16 = impl.unsigned_intFromFloat_f16;
15
16const i32_intFromFloat_f32 = impl.i32_intFromFloat_f32;
17const u32_intFromFloat_f32 = impl.u32_intFromFloat_f32;
18const i64_intFromFloat_f32 = impl.i64_intFromFloat_f32;
19const u64_intFromFloat_f32 = impl.u64_intFromFloat_f32;
20const i128_intFromFloat_f32 = impl.i128_intFromFloat_f32;
21const u128_intFromFloat_f32 = impl.u128_intFromFloat_f32;
22const signed_intFromFloat_f32 = impl.signed_intFromFloat_f32;
23const unsigned_intFromFloat_f32 = impl.unsigned_intFromFloat_f32;
24
25const i32_intFromFloat_f64 = impl.i32_intFromFloat_f64;
26const u32_intFromFloat_f64 = impl.u32_intFromFloat_f64;
27const i64_intFromFloat_f64 = impl.i64_intFromFloat_f64;
28const u64_intFromFloat_f64 = impl.u64_intFromFloat_f64;
29const i128_intFromFloat_f64 = impl.i128_intFromFloat_f64;
30const u128_intFromFloat_f64 = impl.u128_intFromFloat_f64;
31const signed_intFromFloat_f64 = impl.signed_intFromFloat_f64;
32const unsigned_intFromFloat_f64 = impl.unsigned_intFromFloat_f64;
33
34const i32_intFromFloat_f80 = impl.i32_intFromFloat_f80;
35const u32_intFromFloat_f80 = impl.u32_intFromFloat_f80;
36const i64_intFromFloat_f80 = impl.i64_intFromFloat_f80;
37const u64_intFromFloat_f80 = impl.u64_intFromFloat_f80;
38const i128_intFromFloat_f80 = impl.i128_intFromFloat_f80;
39const u128_intFromFloat_f80 = impl.u128_intFromFloat_f80;
40const signed_intFromFloat_f80 = impl.signed_intFromFloat_f80;
41const unsigned_intFromFloat_f80 = impl.unsigned_intFromFloat_f80;
42
43const i32_intFromFloat_f128 = impl.i32_intFromFloat_f128;
44const u32_intFromFloat_f128 = impl.u32_intFromFloat_f128;
45const i64_intFromFloat_f128 = impl.i64_intFromFloat_f128;
46const u64_intFromFloat_f128 = impl.u64_intFromFloat_f128;
47const i128_intFromFloat_f128 = impl.i128_intFromFloat_f128;
48const u128_intFromFloat_f128 = impl.u128_intFromFloat_f128;
49const signed_intFromFloat_f128 = impl.signed_intFromFloat_f128;
50const unsigned_intFromFloat_f128 = impl.unsigned_intFromFloat_f128;
51
52fn test_i32_intFromFloat_f32(a: f32, expected: i32) !void {
53 const x = i32_intFromFloat_f32(a);
3854 try testing.expect(x == expected);
3955}
4056
41fn test__fixunssfsi(a: f32, expected: u32) !void {
42 const x = __fixunssfsi(a);
57fn test_u32_intFromFloat_f32(a: f32, expected: u32) !void {
58 const x = u32_intFromFloat_f32(a);
4359 try testing.expect(x == expected);
4460}
4561
46test "fixsfsi" {
47 try test__fixsfsi(-math.floatMax(f32), math.minInt(i32));
48
49 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
50 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
51
52 try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000);
53 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
54 try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
55
56 try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000);
57 try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000);
58 try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
59 try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
60
61 try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000);
62 try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000);
63
64 try test__fixsfsi(-0x1.000000p+31, -0x80000000);
65 try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000);
66 try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
67 try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
68
69 try test__fixsfsi(-2.01, -2);
70 try test__fixsfsi(-2.0, -2);
71 try test__fixsfsi(-1.99, -1);
72 try test__fixsfsi(-1.0, -1);
73 try test__fixsfsi(-0.99, 0);
74 try test__fixsfsi(-0.5, 0);
75
76 try test__fixsfsi(-math.floatMin(f32), 0);
77 try test__fixsfsi(0.0, 0);
78 try test__fixsfsi(math.floatMin(f32), 0);
79 try test__fixsfsi(0.5, 0);
80 try test__fixsfsi(0.99, 0);
81 try test__fixsfsi(1.0, 1);
82 try test__fixsfsi(1.5, 1);
83 try test__fixsfsi(1.99, 1);
84 try test__fixsfsi(2.0, 2);
85 try test__fixsfsi(2.01, 2);
86
87 try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
88 try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
89 try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF);
90 try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF);
91
92 try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
93 try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
94
95 try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
96 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
97 try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
98 try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
99
100 try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
101 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
102 try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
103
104 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
105 try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
106
107 try test__fixsfsi(math.floatMax(f32), math.maxInt(i32));
62test i32_intFromFloat_f32 {
63 try test_i32_intFromFloat_f32(-math.floatMax(f32), math.minInt(i32));
64
65 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
66 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
67
68 try test_i32_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000);
69 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
70 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
71
72 try test_i32_intFromFloat_f32(-0x1.0000000000001p+63, -0x80000000);
73 try test_i32_intFromFloat_f32(-0x1.0000000000000p+63, -0x80000000);
74 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
75 try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
76
77 try test_i32_intFromFloat_f32(-0x1.FFFFFEp+62, -0x80000000);
78 try test_i32_intFromFloat_f32(-0x1.FFFFFCp+62, -0x80000000);
79
80 try test_i32_intFromFloat_f32(-0x1.000000p+31, -0x80000000);
81 try test_i32_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000);
82 try test_i32_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80);
83 try test_i32_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00);
84
85 try test_i32_intFromFloat_f32(-2.01, -2);
86 try test_i32_intFromFloat_f32(-2.0, -2);
87 try test_i32_intFromFloat_f32(-1.99, -1);
88 try test_i32_intFromFloat_f32(-1.0, -1);
89 try test_i32_intFromFloat_f32(-0.99, 0);
90 try test_i32_intFromFloat_f32(-0.5, 0);
91
92 try test_i32_intFromFloat_f32(-math.floatMin(f32), 0);
93 try test_i32_intFromFloat_f32(0.0, 0);
94 try test_i32_intFromFloat_f32(math.floatMin(f32), 0);
95 try test_i32_intFromFloat_f32(0.5, 0);
96 try test_i32_intFromFloat_f32(0.99, 0);
97 try test_i32_intFromFloat_f32(1.0, 1);
98 try test_i32_intFromFloat_f32(1.5, 1);
99 try test_i32_intFromFloat_f32(1.99, 1);
100 try test_i32_intFromFloat_f32(2.0, 2);
101 try test_i32_intFromFloat_f32(2.01, 2);
102
103 try test_i32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
104 try test_i32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
105 try test_i32_intFromFloat_f32(0x1.FFFFFFp+30, 0x7FFFFFFF);
106 try test_i32_intFromFloat_f32(0x1.000000p+31, 0x7FFFFFFF);
107
108 try test_i32_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFFFF);
109 try test_i32_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFFFF);
110
111 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
112 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
113 try test_i32_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFF);
114 try test_i32_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFF);
115
116 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
117 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
118 try test_i32_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFF);
119
120 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
121 try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
122
123 try test_i32_intFromFloat_f32(math.floatMax(f32), math.maxInt(i32));
108124}
109125
110test "fixunssfsi" {
111 try test__fixunssfsi(0.0, 0);
112
113 try test__fixunssfsi(0.5, 0);
114 try test__fixunssfsi(0.99, 0);
115 try test__fixunssfsi(1.0, 1);
116 try test__fixunssfsi(1.5, 1);
117 try test__fixunssfsi(1.99, 1);
118 try test__fixunssfsi(2.0, 2);
119 try test__fixunssfsi(2.01, 2);
120 try test__fixunssfsi(-0.5, 0);
121 try test__fixunssfsi(-0.99, 0);
122
123 try test__fixunssfsi(-1.0, 0);
124 try test__fixunssfsi(-1.5, 0);
125 try test__fixunssfsi(-1.99, 0);
126 try test__fixunssfsi(-2.0, 0);
127 try test__fixunssfsi(-2.01, 0);
128
129 try test__fixunssfsi(0x1.000000p+31, 0x80000000);
130 try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF);
131 try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00);
132 try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
133 try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
134
135 try test__fixunssfsi(-0x1.FFFFFEp+30, 0);
136 try test__fixunssfsi(-0x1.FFFFFCp+30, 0);
126test u32_intFromFloat_f32 {
127 try test_u32_intFromFloat_f32(0.0, 0);
128
129 try test_u32_intFromFloat_f32(0.5, 0);
130 try test_u32_intFromFloat_f32(0.99, 0);
131 try test_u32_intFromFloat_f32(1.0, 1);
132 try test_u32_intFromFloat_f32(1.5, 1);
133 try test_u32_intFromFloat_f32(1.99, 1);
134 try test_u32_intFromFloat_f32(2.0, 2);
135 try test_u32_intFromFloat_f32(2.01, 2);
136 try test_u32_intFromFloat_f32(-0.5, 0);
137 try test_u32_intFromFloat_f32(-0.99, 0);
138
139 try test_u32_intFromFloat_f32(-1.0, 0);
140 try test_u32_intFromFloat_f32(-1.5, 0);
141 try test_u32_intFromFloat_f32(-1.99, 0);
142 try test_u32_intFromFloat_f32(-2.0, 0);
143 try test_u32_intFromFloat_f32(-2.01, 0);
144
145 try test_u32_intFromFloat_f32(0x1.000000p+31, 0x80000000);
146 try test_u32_intFromFloat_f32(0x1.000000p+32, 0xFFFFFFFF);
147 try test_u32_intFromFloat_f32(0x1.FFFFFEp+31, 0xFFFFFF00);
148 try test_u32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
149 try test_u32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
150
151 try test_u32_intFromFloat_f32(-0x1.FFFFFEp+30, 0);
152 try test_u32_intFromFloat_f32(-0x1.FFFFFCp+30, 0);
137153}
138154
139fn test__fixsfdi(a: f32, expected: i64) !void {
140 const x = __fixsfdi(a);
155fn test_i64_intFromFloat_f32(a: f32, expected: i64) !void {
156 const x = i64_intFromFloat_f32(a);
141157 try testing.expect(x == expected);
142158}
143159
144fn test__fixunssfdi(a: f32, expected: u64) !void {
145 const x = __fixunssfdi(a);
160fn test_u64_intFromFloat_f32(a: f32, expected: u64) !void {
161 const x = u64_intFromFloat_f32(a);
146162 try testing.expect(x == expected);
147163}
148164
149test "fixsfdi" {
150 try test__fixsfdi(-math.floatMax(f32), math.minInt(i64));
151
152 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
153 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
154
155 try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000);
156 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
157 try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
158
159 try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000);
160 try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000);
161 try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
162 try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
163
164 try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000);
165 try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
166 try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
167
168 try test__fixsfdi(-2.01, -2);
169 try test__fixsfdi(-2.0, -2);
170 try test__fixsfdi(-1.99, -1);
171 try test__fixsfdi(-1.0, -1);
172 try test__fixsfdi(-0.99, 0);
173 try test__fixsfdi(-0.5, 0);
174 try test__fixsfdi(-math.floatMin(f32), 0);
175 try test__fixsfdi(0.0, 0);
176 try test__fixsfdi(math.floatMin(f32), 0);
177 try test__fixsfdi(0.5, 0);
178 try test__fixsfdi(0.99, 0);
179 try test__fixsfdi(1.0, 1);
180 try test__fixsfdi(1.5, 1);
181 try test__fixsfdi(1.99, 1);
182 try test__fixsfdi(2.0, 2);
183 try test__fixsfdi(2.01, 2);
184
185 try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
186 try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
187 try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
188
189 try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
190 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
191 try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
192 try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
193
194 try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
195 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
196 try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
197
198 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
199 try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
200
201 try test__fixsfdi(math.floatMax(f32), math.maxInt(i64));
165test i64_intFromFloat_f32 {
166 try test_i64_intFromFloat_f32(-math.floatMax(f32), math.minInt(i64));
167
168 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
169 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
170
171 try test_i64_intFromFloat_f32(-0x1.0000000000000p+127, -0x8000000000000000);
172 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
173 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
174
175 try test_i64_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000);
176 try test_i64_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000);
177 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
178 try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
179
180 try test_i64_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000);
181 try test_i64_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000);
182 try test_i64_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000);
183
184 try test_i64_intFromFloat_f32(-2.01, -2);
185 try test_i64_intFromFloat_f32(-2.0, -2);
186 try test_i64_intFromFloat_f32(-1.99, -1);
187 try test_i64_intFromFloat_f32(-1.0, -1);
188 try test_i64_intFromFloat_f32(-0.99, 0);
189 try test_i64_intFromFloat_f32(-0.5, 0);
190 try test_i64_intFromFloat_f32(-math.floatMin(f32), 0);
191 try test_i64_intFromFloat_f32(0.0, 0);
192 try test_i64_intFromFloat_f32(math.floatMin(f32), 0);
193 try test_i64_intFromFloat_f32(0.5, 0);
194 try test_i64_intFromFloat_f32(0.99, 0);
195 try test_i64_intFromFloat_f32(1.0, 1);
196 try test_i64_intFromFloat_f32(1.5, 1);
197 try test_i64_intFromFloat_f32(1.99, 1);
198 try test_i64_intFromFloat_f32(2.0, 2);
199 try test_i64_intFromFloat_f32(2.01, 2);
200
201 try test_i64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
202 try test_i64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
203 try test_i64_intFromFloat_f32(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
204
205 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
206 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
207 try test_i64_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
208 try test_i64_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
209
210 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
211 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
212 try test_i64_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
213
214 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
215 try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
216
217 try test_i64_intFromFloat_f32(math.floatMax(f32), math.maxInt(i64));
202218}
203219
204test "fixunssfdi" {
205 try test__fixunssfdi(0.0, 0);
206
207 try test__fixunssfdi(0.5, 0);
208 try test__fixunssfdi(0.99, 0);
209 try test__fixunssfdi(1.0, 1);
210 try test__fixunssfdi(1.5, 1);
211 try test__fixunssfdi(1.99, 1);
212 try test__fixunssfdi(2.0, 2);
213 try test__fixunssfdi(2.01, 2);
214 try test__fixunssfdi(-0.5, 0);
215 try test__fixunssfdi(-0.99, 0);
216
217 try test__fixunssfdi(-1.0, 0);
218 try test__fixunssfdi(-1.5, 0);
219 try test__fixunssfdi(-1.99, 0);
220 try test__fixunssfdi(-2.0, 0);
221 try test__fixunssfdi(-2.01, 0);
222
223 try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
224 try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000);
225 try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
226 try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
227
228 try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000);
229 try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000);
220test u64_intFromFloat_f32 {
221 try test_u64_intFromFloat_f32(0.0, 0);
222
223 try test_u64_intFromFloat_f32(0.5, 0);
224 try test_u64_intFromFloat_f32(0.99, 0);
225 try test_u64_intFromFloat_f32(1.0, 1);
226 try test_u64_intFromFloat_f32(1.5, 1);
227 try test_u64_intFromFloat_f32(1.99, 1);
228 try test_u64_intFromFloat_f32(2.0, 2);
229 try test_u64_intFromFloat_f32(2.01, 2);
230 try test_u64_intFromFloat_f32(-0.5, 0);
231 try test_u64_intFromFloat_f32(-0.99, 0);
232
233 try test_u64_intFromFloat_f32(-1.0, 0);
234 try test_u64_intFromFloat_f32(-1.5, 0);
235 try test_u64_intFromFloat_f32(-1.99, 0);
236 try test_u64_intFromFloat_f32(-2.0, 0);
237 try test_u64_intFromFloat_f32(-2.01, 0);
238
239 try test_u64_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
240 try test_u64_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000);
241 try test_u64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
242 try test_u64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
243
244 try test_u64_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000);
245 try test_u64_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000);
230246}
231247
232fn test__fixsfti(a: f32, expected: i128) !void {
233 const x = __fixsfti(a);
248fn test_i128_intFromFloat_f32(a: f32, expected: i128) !void {
249 const x = i128_intFromFloat_f32(a);
234250 try testing.expect(x == expected);
235251}
236252
237fn test__fixunssfti(a: f32, expected: u128) !void {
238 const x = __fixunssfti(a);
253fn test_u128_intFromFloat_f32(a: f32, expected: u128) !void {
254 const x = u128_intFromFloat_f32(a);
239255 try testing.expect(x == expected);
240256}
241257
242test "fixsfti" {
243 try test__fixsfti(-math.floatMax(f32), math.minInt(i128));
244
245 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
246 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
247
248 try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
249 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
250 try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
251 try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
252 try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
253 try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
254
255 try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000);
256 try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000);
257 try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
258 try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
259
260 try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000);
261 try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
262 try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
263
264 try test__fixsfti(-0x1.000000p+31, -0x80000000);
265 try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000);
266 try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80);
267 try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00);
268
269 try test__fixsfti(-2.01, -2);
270 try test__fixsfti(-2.0, -2);
271 try test__fixsfti(-1.99, -1);
272 try test__fixsfti(-1.0, -1);
273 try test__fixsfti(-0.99, 0);
274 try test__fixsfti(-0.5, 0);
275 try test__fixsfti(-math.floatMin(f32), 0);
276 try test__fixsfti(0.0, 0);
277 try test__fixsfti(math.floatMin(f32), 0);
278 try test__fixsfti(0.5, 0);
279 try test__fixsfti(0.99, 0);
280 try test__fixsfti(1.0, 1);
281 try test__fixsfti(1.5, 1);
282 try test__fixsfti(1.99, 1);
283 try test__fixsfti(2.0, 2);
284 try test__fixsfti(2.01, 2);
285
286 try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00);
287 try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80);
288 try test__fixsfti(0x1.FFFFFFp+30, 0x80000000);
289 try test__fixsfti(0x1.000000p+31, 0x80000000);
290
291 try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
292 try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
293 try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000);
294
295 try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
296 try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
297 try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000);
298 try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000);
299
300 try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
301 try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
302 try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
303 try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
304 try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
305 try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
306
307 try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
308 try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
309
310 try test__fixsfti(math.floatMax(f32), math.maxInt(i128));
258test i128_intFromFloat_f32 {
259 try test_i128_intFromFloat_f32(-math.floatMax(f32), math.minInt(i128));
260
261 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
262 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
263
264 try test_i128_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
265 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
266 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
267 try test_i128_intFromFloat_f32(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
268 try test_i128_intFromFloat_f32(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
269 try test_i128_intFromFloat_f32(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
270
271 try test_i128_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000);
272 try test_i128_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000);
273 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
274 try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
275
276 try test_i128_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000);
277 try test_i128_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000);
278 try test_i128_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000);
279
280 try test_i128_intFromFloat_f32(-0x1.000000p+31, -0x80000000);
281 try test_i128_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000);
282 try test_i128_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80);
283 try test_i128_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00);
284
285 try test_i128_intFromFloat_f32(-2.01, -2);
286 try test_i128_intFromFloat_f32(-2.0, -2);
287 try test_i128_intFromFloat_f32(-1.99, -1);
288 try test_i128_intFromFloat_f32(-1.0, -1);
289 try test_i128_intFromFloat_f32(-0.99, 0);
290 try test_i128_intFromFloat_f32(-0.5, 0);
291 try test_i128_intFromFloat_f32(-math.floatMin(f32), 0);
292 try test_i128_intFromFloat_f32(0.0, 0);
293 try test_i128_intFromFloat_f32(math.floatMin(f32), 0);
294 try test_i128_intFromFloat_f32(0.5, 0);
295 try test_i128_intFromFloat_f32(0.99, 0);
296 try test_i128_intFromFloat_f32(1.0, 1);
297 try test_i128_intFromFloat_f32(1.5, 1);
298 try test_i128_intFromFloat_f32(1.99, 1);
299 try test_i128_intFromFloat_f32(2.0, 2);
300 try test_i128_intFromFloat_f32(2.01, 2);
301
302 try test_i128_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00);
303 try test_i128_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80);
304 try test_i128_intFromFloat_f32(0x1.FFFFFFp+30, 0x80000000);
305 try test_i128_intFromFloat_f32(0x1.000000p+31, 0x80000000);
306
307 try test_i128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
308 try test_i128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
309 try test_i128_intFromFloat_f32(0x1.FFFFFFp+62, 0x8000000000000000);
310
311 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
312 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
313 try test_i128_intFromFloat_f32(0x1.0000000000000p+63, 0x8000000000000000);
314 try test_i128_intFromFloat_f32(0x1.0000000000001p+63, 0x8000000000000000);
315
316 try test_i128_intFromFloat_f32(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
317 try test_i128_intFromFloat_f32(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
318 try test_i128_intFromFloat_f32(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
319 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
320 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
321 try test_i128_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
322
323 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
324 try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
325
326 try test_i128_intFromFloat_f32(math.floatMax(f32), math.maxInt(i128));
311327}
312328
313test "fixunssfti" {
314 try test__fixunssfti(0.0, 0);
315
316 try test__fixunssfti(0.5, 0);
317 try test__fixunssfti(0.99, 0);
318 try test__fixunssfti(1.0, 1);
319 try test__fixunssfti(1.5, 1);
320 try test__fixunssfti(1.99, 1);
321 try test__fixunssfti(2.0, 2);
322 try test__fixunssfti(2.01, 2);
323 try test__fixunssfti(-0.5, 0);
324 try test__fixunssfti(-0.99, 0);
325
326 try test__fixunssfti(-1.0, 0);
327 try test__fixunssfti(-1.5, 0);
328 try test__fixunssfti(-1.99, 0);
329 try test__fixunssfti(-2.0, 0);
330 try test__fixunssfti(-2.01, 0);
331
332 try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
333 try test__fixunssfti(0x1.000000p+63, 0x8000000000000000);
334 try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
335 try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
336 try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);
337 try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000);
338 try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);
339 try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);
340
341 try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000);
342 try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000);
343 try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000);
344 try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000);
345 try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000);
346 try test__fixunssfti(math.inf(f32), math.maxInt(u128));
329test u128_intFromFloat_f32 {
330 try test_u128_intFromFloat_f32(0.0, 0);
331
332 try test_u128_intFromFloat_f32(0.5, 0);
333 try test_u128_intFromFloat_f32(0.99, 0);
334 try test_u128_intFromFloat_f32(1.0, 1);
335 try test_u128_intFromFloat_f32(1.5, 1);
336 try test_u128_intFromFloat_f32(1.99, 1);
337 try test_u128_intFromFloat_f32(2.0, 2);
338 try test_u128_intFromFloat_f32(2.01, 2);
339 try test_u128_intFromFloat_f32(-0.5, 0);
340 try test_u128_intFromFloat_f32(-0.99, 0);
341
342 try test_u128_intFromFloat_f32(-1.0, 0);
343 try test_u128_intFromFloat_f32(-1.5, 0);
344 try test_u128_intFromFloat_f32(-1.99, 0);
345 try test_u128_intFromFloat_f32(-2.0, 0);
346 try test_u128_intFromFloat_f32(-2.01, 0);
347
348 try test_u128_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
349 try test_u128_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000);
350 try test_u128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
351 try test_u128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
352 try test_u128_intFromFloat_f32(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);
353 try test_u128_intFromFloat_f32(0x1.000000p+127, 0x80000000000000000000000000000000);
354 try test_u128_intFromFloat_f32(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);
355 try test_u128_intFromFloat_f32(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);
356
357 try test_u128_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000);
358 try test_u128_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000);
359 try test_u128_intFromFloat_f32(-0x1.FFFFFEp+126, 0x0000000000000000);
360 try test_u128_intFromFloat_f32(-0x1.FFFFFCp+126, 0x0000000000000000);
361 try test_u128_intFromFloat_f32(math.floatMax(f32), 0xffffff00000000000000000000000000);
362 try test_u128_intFromFloat_f32(math.inf(f32), math.maxInt(u128));
347363}
348364
349fn test_fixsfei(comptime T: type, expected: T, a: f32) !void {
365fn test_intFromFloat_f32(comptime T: type, expected: T, a: f32) !void {
350366 const int = @typeInfo(T).int;
351367 var actual: T = undefined;
352368 _ = switch (int.signedness) {
353 .signed => __fixsfei,
354 .unsigned => __fixunssfei,
355 }(@ptrCast(&actual), int.bits, a);
369 .signed => signed_intFromFloat_f32,
370 .unsigned => unsigned_intFromFloat_f32,
371 }(@ptrCast(&actual), a);
356372 try testing.expect(expected == actual);
357373}
358374
359test "fixsfei" {
360 try test_fixsfei(i256, -1 << 127, -0x1p127);
361 try test_fixsfei(i256, -1 << 100, -0x1p100);
362 try test_fixsfei(i256, -1 << 50, -0x1p50);
363 try test_fixsfei(i256, -1 << 1, -0x1p1);
364 try test_fixsfei(i256, -1 << 0, -0x1p0);
365 try test_fixsfei(i256, 0, 0);
366 try test_fixsfei(i256, 1 << 0, 0x1p0);
367 try test_fixsfei(i256, 1 << 1, 0x1p1);
368 try test_fixsfei(i256, 1 << 50, 0x1p50);
369 try test_fixsfei(i256, 1 << 100, 0x1p100);
370 try test_fixsfei(i256, 1 << 127, 0x1p127);
375test signed_intFromFloat_f32 {
376 try test_intFromFloat_f32(i256, -1 << 127, -0x1p127);
377 try test_intFromFloat_f32(i256, -1 << 100, -0x1p100);
378 try test_intFromFloat_f32(i256, -1 << 50, -0x1p50);
379 try test_intFromFloat_f32(i256, -1 << 1, -0x1p1);
380 try test_intFromFloat_f32(i256, -1 << 0, -0x1p0);
381 try test_intFromFloat_f32(i256, 0, 0);
382 try test_intFromFloat_f32(i256, 1 << 0, 0x1p0);
383 try test_intFromFloat_f32(i256, 1 << 1, 0x1p1);
384 try test_intFromFloat_f32(i256, 1 << 50, 0x1p50);
385 try test_intFromFloat_f32(i256, 1 << 100, 0x1p100);
386 try test_intFromFloat_f32(i256, 1 << 127, 0x1p127);
371387}
372388
373test "fixunsfei" {
374 try test_fixsfei(u256, 0, 0);
375 try test_fixsfei(u256, 1 << 0, 0x1p0);
376 try test_fixsfei(u256, 1 << 1, 0x1p1);
377 try test_fixsfei(u256, 1 << 50, 0x1p50);
378 try test_fixsfei(u256, 1 << 100, 0x1p100);
379 try test_fixsfei(u256, 1 << 127, 0x1p127);
389test unsigned_intFromFloat_f32 {
390 try test_intFromFloat_f32(u256, 0, 0);
391 try test_intFromFloat_f32(u256, 1 << 0, 0x1p0);
392 try test_intFromFloat_f32(u256, 1 << 1, 0x1p1);
393 try test_intFromFloat_f32(u256, 1 << 50, 0x1p50);
394 try test_intFromFloat_f32(u256, 1 << 100, 0x1p100);
395 try test_intFromFloat_f32(u256, 1 << 127, 0x1p127);
380396}
381397
382fn test__fixdfsi(a: f64, expected: i32) !void {
383 const x = __fixdfsi(a);
398fn test_i32_intFromFloat_f64(a: f64, expected: i32) !void {
399 const x = i32_intFromFloat_f64(a);
384400 try testing.expect(x == expected);
385401}
386402
387fn test__fixunsdfsi(a: f64, expected: u32) !void {
388 const x = __fixunsdfsi(a);
403fn test_u32_intFromFloat_f64(a: f64, expected: u32) !void {
404 const x = u32_intFromFloat_f64(a);
389405 try testing.expect(x == expected);
390406}
391407
392test "fixdfsi" {
393 try test__fixdfsi(-math.floatMax(f64), math.minInt(i32));
394
395 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
396 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
397
398 try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
399 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
400 try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
401
402 try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
403 try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
404 try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
405 try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
406
407 try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
408 try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);
409
410 try test__fixdfsi(-0x1.000000p+31, -0x80000000);
411 try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
412 try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
413
414 try test__fixdfsi(-2.01, -2);
415 try test__fixdfsi(-2.0, -2);
416 try test__fixdfsi(-1.99, -1);
417 try test__fixdfsi(-1.0, -1);
418 try test__fixdfsi(-0.99, 0);
419 try test__fixdfsi(-0.5, 0);
420 try test__fixdfsi(-math.floatMin(f64), 0);
421 try test__fixdfsi(0.0, 0);
422 try test__fixdfsi(math.floatMin(f64), 0);
423 try test__fixdfsi(0.5, 0);
424 try test__fixdfsi(0.99, 0);
425 try test__fixdfsi(1.0, 1);
426 try test__fixdfsi(1.5, 1);
427 try test__fixdfsi(1.99, 1);
428 try test__fixdfsi(2.0, 2);
429 try test__fixdfsi(2.01, 2);
430
431 try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
432 try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
433 try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);
434
435 try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
436 try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
437
438 try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
439 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
440 try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
441 try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
442
443 try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
444 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
445 try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
446
447 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
448 try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
449
450 try test__fixdfsi(math.floatMax(f64), math.maxInt(i32));
408test i32_intFromFloat_f64 {
409 try test_i32_intFromFloat_f64(-math.floatMax(f64), math.minInt(i32));
410
411 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
412 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
413
414 try test_i32_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000);
415 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
416 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
417
418 try test_i32_intFromFloat_f64(-0x1.0000000000001p+63, -0x80000000);
419 try test_i32_intFromFloat_f64(-0x1.0000000000000p+63, -0x80000000);
420 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
421 try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
422
423 try test_i32_intFromFloat_f64(-0x1.FFFFFEp+62, -0x80000000);
424 try test_i32_intFromFloat_f64(-0x1.FFFFFCp+62, -0x80000000);
425
426 try test_i32_intFromFloat_f64(-0x1.000000p+31, -0x80000000);
427 try test_i32_intFromFloat_f64(-0x1.FFFFFFp+30, -0x7FFFFFC0);
428 try test_i32_intFromFloat_f64(-0x1.FFFFFEp+30, -0x7FFFFF80);
429
430 try test_i32_intFromFloat_f64(-2.01, -2);
431 try test_i32_intFromFloat_f64(-2.0, -2);
432 try test_i32_intFromFloat_f64(-1.99, -1);
433 try test_i32_intFromFloat_f64(-1.0, -1);
434 try test_i32_intFromFloat_f64(-0.99, 0);
435 try test_i32_intFromFloat_f64(-0.5, 0);
436 try test_i32_intFromFloat_f64(-math.floatMin(f64), 0);
437 try test_i32_intFromFloat_f64(0.0, 0);
438 try test_i32_intFromFloat_f64(math.floatMin(f64), 0);
439 try test_i32_intFromFloat_f64(0.5, 0);
440 try test_i32_intFromFloat_f64(0.99, 0);
441 try test_i32_intFromFloat_f64(1.0, 1);
442 try test_i32_intFromFloat_f64(1.5, 1);
443 try test_i32_intFromFloat_f64(1.99, 1);
444 try test_i32_intFromFloat_f64(2.0, 2);
445 try test_i32_intFromFloat_f64(2.01, 2);
446
447 try test_i32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80);
448 try test_i32_intFromFloat_f64(0x1.FFFFFFp+30, 0x7FFFFFC0);
449 try test_i32_intFromFloat_f64(0x1.000000p+31, 0x7FFFFFFF);
450
451 try test_i32_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFFFF);
452 try test_i32_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFFFF);
453
454 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
455 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
456 try test_i32_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFF);
457 try test_i32_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFF);
458
459 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
460 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
461 try test_i32_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFF);
462
463 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
464 try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
465
466 try test_i32_intFromFloat_f64(math.floatMax(f64), math.maxInt(i32));
451467}
452468
453test "fixunsdfsi" {
454 try test__fixunsdfsi(0.0, 0);
455
456 try test__fixunsdfsi(0.5, 0);
457 try test__fixunsdfsi(0.99, 0);
458 try test__fixunsdfsi(1.0, 1);
459 try test__fixunsdfsi(1.5, 1);
460 try test__fixunsdfsi(1.99, 1);
461 try test__fixunsdfsi(2.0, 2);
462 try test__fixunsdfsi(2.01, 2);
463 try test__fixunsdfsi(-0.5, 0);
464 try test__fixunsdfsi(-0.99, 0);
465 try test__fixunsdfsi(-1.0, 0);
466 try test__fixunsdfsi(-1.5, 0);
467 try test__fixunsdfsi(-1.99, 0);
468 try test__fixunsdfsi(-2.0, 0);
469 try test__fixunsdfsi(-2.01, 0);
470
471 try test__fixunsdfsi(0x1.000000p+31, 0x80000000);
472 try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF);
473 try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00);
474 try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
475 try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
476
477 try test__fixunsdfsi(-0x1.FFFFFEp+30, 0);
478 try test__fixunsdfsi(-0x1.FFFFFCp+30, 0);
479
480 try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF);
481 try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);
482 try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);
469test u32_intFromFloat_f64 {
470 try test_u32_intFromFloat_f64(0.0, 0);
471
472 try test_u32_intFromFloat_f64(0.5, 0);
473 try test_u32_intFromFloat_f64(0.99, 0);
474 try test_u32_intFromFloat_f64(1.0, 1);
475 try test_u32_intFromFloat_f64(1.5, 1);
476 try test_u32_intFromFloat_f64(1.99, 1);
477 try test_u32_intFromFloat_f64(2.0, 2);
478 try test_u32_intFromFloat_f64(2.01, 2);
479 try test_u32_intFromFloat_f64(-0.5, 0);
480 try test_u32_intFromFloat_f64(-0.99, 0);
481 try test_u32_intFromFloat_f64(-1.0, 0);
482 try test_u32_intFromFloat_f64(-1.5, 0);
483 try test_u32_intFromFloat_f64(-1.99, 0);
484 try test_u32_intFromFloat_f64(-2.0, 0);
485 try test_u32_intFromFloat_f64(-2.01, 0);
486
487 try test_u32_intFromFloat_f64(0x1.000000p+31, 0x80000000);
488 try test_u32_intFromFloat_f64(0x1.000000p+32, 0xFFFFFFFF);
489 try test_u32_intFromFloat_f64(0x1.FFFFFEp+31, 0xFFFFFF00);
490 try test_u32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80);
491 try test_u32_intFromFloat_f64(0x1.FFFFFCp+30, 0x7FFFFF00);
492
493 try test_u32_intFromFloat_f64(-0x1.FFFFFEp+30, 0);
494 try test_u32_intFromFloat_f64(-0x1.FFFFFCp+30, 0);
495
496 try test_u32_intFromFloat_f64(0x1.FFFFFFFEp+31, 0xFFFFFFFF);
497 try test_u32_intFromFloat_f64(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);
498 try test_u32_intFromFloat_f64(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);
483499}
484500
485fn test__fixdfdi(a: f64, expected: i64) !void {
486 const x = __fixdfdi(a);
501fn test_i64_intFromFloat_f64(a: f64, expected: i64) !void {
502 const x = i64_intFromFloat_f64(a);
487503 try testing.expect(x == expected);
488504}
489505
490fn test__fixunsdfdi(a: f64, expected: u64) !void {
491 const x = __fixunsdfdi(a);
506fn test_u64_intFromFloat_f64(a: f64, expected: u64) !void {
507 const x = u64_intFromFloat_f64(a);
492508 try testing.expect(x == expected);
493509}
494510
495test "fixdfdi" {
496 try test__fixdfdi(-math.floatMax(f64), math.minInt(i64));
497
498 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
499 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
500
501 try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
502 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
503 try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
504
505 try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
506 try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
507 try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
508 try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
509
510 try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
511 try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
512
513 try test__fixdfdi(-2.01, -2);
514 try test__fixdfdi(-2.0, -2);
515 try test__fixdfdi(-1.99, -1);
516 try test__fixdfdi(-1.0, -1);
517 try test__fixdfdi(-0.99, 0);
518 try test__fixdfdi(-0.5, 0);
519 try test__fixdfdi(-math.floatMin(f64), 0);
520 try test__fixdfdi(0.0, 0);
521 try test__fixdfdi(math.floatMin(f64), 0);
522 try test__fixdfdi(0.5, 0);
523 try test__fixdfdi(0.99, 0);
524 try test__fixdfdi(1.0, 1);
525 try test__fixdfdi(1.5, 1);
526 try test__fixdfdi(1.99, 1);
527 try test__fixdfdi(2.0, 2);
528 try test__fixdfdi(2.01, 2);
529
530 try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
531 try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
532
533 try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
534 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
535 try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
536 try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
537
538 try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
539 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
540 try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
541
542 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
543 try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
544
545 try test__fixdfdi(math.floatMax(f64), math.maxInt(i64));
511test i64_intFromFloat_f64 {
512 try test_i64_intFromFloat_f64(-math.floatMax(f64), math.minInt(i64));
513
514 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
515 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
516
517 try test_i64_intFromFloat_f64(-0x1.0000000000000p+127, -0x8000000000000000);
518 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
519 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
520
521 try test_i64_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000000);
522 try test_i64_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000);
523 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
524 try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
525
526 try test_i64_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000);
527 try test_i64_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000);
528
529 try test_i64_intFromFloat_f64(-2.01, -2);
530 try test_i64_intFromFloat_f64(-2.0, -2);
531 try test_i64_intFromFloat_f64(-1.99, -1);
532 try test_i64_intFromFloat_f64(-1.0, -1);
533 try test_i64_intFromFloat_f64(-0.99, 0);
534 try test_i64_intFromFloat_f64(-0.5, 0);
535 try test_i64_intFromFloat_f64(-math.floatMin(f64), 0);
536 try test_i64_intFromFloat_f64(0.0, 0);
537 try test_i64_intFromFloat_f64(math.floatMin(f64), 0);
538 try test_i64_intFromFloat_f64(0.5, 0);
539 try test_i64_intFromFloat_f64(0.99, 0);
540 try test_i64_intFromFloat_f64(1.0, 1);
541 try test_i64_intFromFloat_f64(1.5, 1);
542 try test_i64_intFromFloat_f64(1.99, 1);
543 try test_i64_intFromFloat_f64(2.0, 2);
544 try test_i64_intFromFloat_f64(2.01, 2);
545
546 try test_i64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
547 try test_i64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
548
549 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
550 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
551 try test_i64_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
552 try test_i64_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
553
554 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
555 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
556 try test_i64_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
557
558 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
559 try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
560
561 try test_i64_intFromFloat_f64(math.floatMax(f64), math.maxInt(i64));
546562}
547563
548test "fixunsdfdi" {
549 try test__fixunsdfdi(0.0, 0);
550 try test__fixunsdfdi(0.5, 0);
551 try test__fixunsdfdi(0.99, 0);
552 try test__fixunsdfdi(1.0, 1);
553 try test__fixunsdfdi(1.5, 1);
554 try test__fixunsdfdi(1.99, 1);
555 try test__fixunsdfdi(2.0, 2);
556 try test__fixunsdfdi(2.01, 2);
557 try test__fixunsdfdi(-0.5, 0);
558 try test__fixunsdfdi(-0.99, 0);
559 try test__fixunsdfdi(-1.0, 0);
560 try test__fixunsdfdi(-1.5, 0);
561 try test__fixunsdfdi(-1.99, 0);
562 try test__fixunsdfdi(-2.0, 0);
563 try test__fixunsdfdi(-2.01, 0);
564
565 try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
566 try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
567
568 try test__fixunsdfdi(-0x1.FFFFFEp+62, 0);
569 try test__fixunsdfdi(-0x1.FFFFFCp+62, 0);
570
571 try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
572 try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000);
573 try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
574 try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
575
576 try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
577 try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
564test u64_intFromFloat_f64 {
565 try test_u64_intFromFloat_f64(0.0, 0);
566 try test_u64_intFromFloat_f64(0.5, 0);
567 try test_u64_intFromFloat_f64(0.99, 0);
568 try test_u64_intFromFloat_f64(1.0, 1);
569 try test_u64_intFromFloat_f64(1.5, 1);
570 try test_u64_intFromFloat_f64(1.99, 1);
571 try test_u64_intFromFloat_f64(2.0, 2);
572 try test_u64_intFromFloat_f64(2.01, 2);
573 try test_u64_intFromFloat_f64(-0.5, 0);
574 try test_u64_intFromFloat_f64(-0.99, 0);
575 try test_u64_intFromFloat_f64(-1.0, 0);
576 try test_u64_intFromFloat_f64(-1.5, 0);
577 try test_u64_intFromFloat_f64(-1.99, 0);
578 try test_u64_intFromFloat_f64(-2.0, 0);
579 try test_u64_intFromFloat_f64(-2.01, 0);
580
581 try test_u64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
582 try test_u64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
583
584 try test_u64_intFromFloat_f64(-0x1.FFFFFEp+62, 0);
585 try test_u64_intFromFloat_f64(-0x1.FFFFFCp+62, 0);
586
587 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
588 try test_u64_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
589 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
590 try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
591
592 try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0);
593 try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0);
578594}
579595
580fn test__fixdfti(a: f64, expected: i128) !void {
581 const x = __fixdfti(a);
596fn test_i128_intFromFloat_f64(a: f64, expected: i128) !void {
597 const x = i128_intFromFloat_f64(a);
582598 try testing.expect(x == expected);
583599}
584600
585fn test__fixunsdfti(a: f64, expected: u128) !void {
586 const x = __fixunsdfti(a);
601fn test_u128_intFromFloat_f64(a: f64, expected: u128) !void {
602 const x = u128_intFromFloat_f64(a);
587603 try testing.expect(x == expected);
588604}
589605
590test "fixdfti" {
591 try test__fixdfti(-math.floatMax(f64), math.minInt(i128));
592
593 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
594 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
595
596 try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
597 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
598 try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
599
600 try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
601 try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
602 try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
603 try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
604
605 try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
606 try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
607
608 try test__fixdfti(-2.01, -2);
609 try test__fixdfti(-2.0, -2);
610 try test__fixdfti(-1.99, -1);
611 try test__fixdfti(-1.0, -1);
612 try test__fixdfti(-0.99, 0);
613 try test__fixdfti(-0.5, 0);
614 try test__fixdfti(-math.floatMin(f64), 0);
615 try test__fixdfti(0.0, 0);
616 try test__fixdfti(math.floatMin(f64), 0);
617 try test__fixdfti(0.5, 0);
618 try test__fixdfti(0.99, 0);
619 try test__fixdfti(1.0, 1);
620 try test__fixdfti(1.5, 1);
621 try test__fixdfti(1.99, 1);
622 try test__fixdfti(2.0, 2);
623 try test__fixdfti(2.01, 2);
624
625 try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
626 try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
627
628 try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
629 try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
630 try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
631 try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);
632
633 try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
634 try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
635 try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
636
637 try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
638 try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
639
640 try test__fixdfti(math.floatMax(f64), math.maxInt(i128));
606test i128_intFromFloat_f64 {
607 try test_i128_intFromFloat_f64(-math.floatMax(f64), math.minInt(i128));
608
609 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
610 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
611
612 try test_i128_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
613 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
614 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
615
616 try test_i128_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000800);
617 try test_i128_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000);
618 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
619 try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
620
621 try test_i128_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000);
622 try test_i128_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000);
623
624 try test_i128_intFromFloat_f64(-2.01, -2);
625 try test_i128_intFromFloat_f64(-2.0, -2);
626 try test_i128_intFromFloat_f64(-1.99, -1);
627 try test_i128_intFromFloat_f64(-1.0, -1);
628 try test_i128_intFromFloat_f64(-0.99, 0);
629 try test_i128_intFromFloat_f64(-0.5, 0);
630 try test_i128_intFromFloat_f64(-math.floatMin(f64), 0);
631 try test_i128_intFromFloat_f64(0.0, 0);
632 try test_i128_intFromFloat_f64(math.floatMin(f64), 0);
633 try test_i128_intFromFloat_f64(0.5, 0);
634 try test_i128_intFromFloat_f64(0.99, 0);
635 try test_i128_intFromFloat_f64(1.0, 1);
636 try test_i128_intFromFloat_f64(1.5, 1);
637 try test_i128_intFromFloat_f64(1.99, 1);
638 try test_i128_intFromFloat_f64(2.0, 2);
639 try test_i128_intFromFloat_f64(2.01, 2);
640
641 try test_i128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
642 try test_i128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
643
644 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
645 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
646 try test_i128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
647 try test_i128_intFromFloat_f64(0x1.0000000000001p+63, 0x8000000000000800);
648
649 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
650 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
651 try test_i128_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
652
653 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
654 try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
655
656 try test_i128_intFromFloat_f64(math.floatMax(f64), math.maxInt(i128));
641657}
642658
643test "fixunsdfti" {
644 try test__fixunsdfti(0.0, 0);
645
646 try test__fixunsdfti(0.5, 0);
647 try test__fixunsdfti(0.99, 0);
648 try test__fixunsdfti(1.0, 1);
649 try test__fixunsdfti(1.5, 1);
650 try test__fixunsdfti(1.99, 1);
651 try test__fixunsdfti(2.0, 2);
652 try test__fixunsdfti(2.01, 2);
653 try test__fixunsdfti(-0.5, 0);
654 try test__fixunsdfti(-0.99, 0);
655 try test__fixunsdfti(-1.0, 0);
656 try test__fixunsdfti(-1.5, 0);
657 try test__fixunsdfti(-1.99, 0);
658 try test__fixunsdfti(-2.0, 0);
659 try test__fixunsdfti(-2.01, 0);
660
661 try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
662 try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
663
664 try test__fixunsdfti(-0x1.FFFFFEp+62, 0);
665 try test__fixunsdfti(-0x1.FFFFFCp+62, 0);
666
667 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
668 try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000);
669 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
670 try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
671
672 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);
673 try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000);
674 try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
675 try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
676 try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
677
678 try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0);
679 try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);
659test u128_intFromFloat_f64 {
660 try test_u128_intFromFloat_f64(0.0, 0);
661
662 try test_u128_intFromFloat_f64(0.5, 0);
663 try test_u128_intFromFloat_f64(0.99, 0);
664 try test_u128_intFromFloat_f64(1.0, 1);
665 try test_u128_intFromFloat_f64(1.5, 1);
666 try test_u128_intFromFloat_f64(1.99, 1);
667 try test_u128_intFromFloat_f64(2.0, 2);
668 try test_u128_intFromFloat_f64(2.01, 2);
669 try test_u128_intFromFloat_f64(-0.5, 0);
670 try test_u128_intFromFloat_f64(-0.99, 0);
671 try test_u128_intFromFloat_f64(-1.0, 0);
672 try test_u128_intFromFloat_f64(-1.5, 0);
673 try test_u128_intFromFloat_f64(-1.99, 0);
674 try test_u128_intFromFloat_f64(-2.0, 0);
675 try test_u128_intFromFloat_f64(-2.01, 0);
676
677 try test_u128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
678 try test_u128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
679
680 try test_u128_intFromFloat_f64(-0x1.FFFFFEp+62, 0);
681 try test_u128_intFromFloat_f64(-0x1.FFFFFCp+62, 0);
682
683 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
684 try test_u128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000);
685 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
686 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
687
688 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);
689 try test_u128_intFromFloat_f64(0x1.0000000000000p+127, 0x80000000000000000000000000000000);
690 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
691 try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
692 try test_u128_intFromFloat_f64(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
693
694 try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0);
695 try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0);
680696}
681697
682fn test_fixdfei(comptime T: type, expected: T, a: f64) !void {
698fn test_intFromFloat_f64(comptime T: type, expected: T, a: f64) !void {
683699 const int = @typeInfo(T).int;
684700 var actual: T = undefined;
685701 _ = switch (int.signedness) {
686 .signed => __fixdfei,
687 .unsigned => __fixunsdfei,
688 }(@ptrCast(&actual), int.bits, a);
702 .signed => signed_intFromFloat_f64,
703 .unsigned => unsigned_intFromFloat_f64,
704 }(@ptrCast(&actual), a);
689705 try testing.expect(expected == actual);
690706}
691707
692test "fixdfei" {
693 try test_fixdfei(i256, -1 << 255, -0x1p255);
694 try test_fixdfei(i256, -1 << 127, -0x1p127);
695 try test_fixdfei(i256, -1 << 100, -0x1p100);
696 try test_fixdfei(i256, -1 << 50, -0x1p50);
697 try test_fixdfei(i256, -1 << 1, -0x1p1);
698 try test_fixdfei(i256, -1 << 0, -0x1p0);
699 try test_fixdfei(i256, 0, 0);
700 try test_fixdfei(i256, 1 << 0, 0x1p0);
701 try test_fixdfei(i256, 1 << 1, 0x1p1);
702 try test_fixdfei(i256, 1 << 50, 0x1p50);
703 try test_fixdfei(i256, 1 << 100, 0x1p100);
704 try test_fixdfei(i256, 1 << 127, 0x1p127);
705 try test_fixdfei(i256, 1 << 254, 0x1p254);
708test signed_intFromFloat_f64 {
709 try test_intFromFloat_f64(i256, -1 << 255, -0x1p255);
710 try test_intFromFloat_f64(i256, -1 << 127, -0x1p127);
711 try test_intFromFloat_f64(i256, -1 << 100, -0x1p100);
712 try test_intFromFloat_f64(i256, -1 << 50, -0x1p50);
713 try test_intFromFloat_f64(i256, -1 << 1, -0x1p1);
714 try test_intFromFloat_f64(i256, -1 << 0, -0x1p0);
715 try test_intFromFloat_f64(i256, 0, 0);
716 try test_intFromFloat_f64(i256, 1 << 0, 0x1p0);
717 try test_intFromFloat_f64(i256, 1 << 1, 0x1p1);
718 try test_intFromFloat_f64(i256, 1 << 50, 0x1p50);
719 try test_intFromFloat_f64(i256, 1 << 100, 0x1p100);
720 try test_intFromFloat_f64(i256, 1 << 127, 0x1p127);
721 try test_intFromFloat_f64(i256, 1 << 254, 0x1p254);
706722}
707723
708test "fixundfei" {
709 try test_fixdfei(u256, 0, 0);
710 try test_fixdfei(u256, 1 << 0, 0x1p0);
711 try test_fixdfei(u256, 1 << 1, 0x1p1);
712 try test_fixdfei(u256, 1 << 50, 0x1p50);
713 try test_fixdfei(u256, 1 << 100, 0x1p100);
714 try test_fixdfei(u256, 1 << 127, 0x1p127);
715 try test_fixdfei(u256, 1 << 255, 0x1p255);
724test unsigned_intFromFloat_f64 {
725 try test_intFromFloat_f64(u256, 0, 0);
726 try test_intFromFloat_f64(u256, 1 << 0, 0x1p0);
727 try test_intFromFloat_f64(u256, 1 << 1, 0x1p1);
728 try test_intFromFloat_f64(u256, 1 << 50, 0x1p50);
729 try test_intFromFloat_f64(u256, 1 << 100, 0x1p100);
730 try test_intFromFloat_f64(u256, 1 << 127, 0x1p127);
731 try test_intFromFloat_f64(u256, 1 << 255, 0x1p255);
716732}
717733
718fn test__fixtfsi(a: f128, expected: i32) !void {
719 const x = __fixtfsi(a);
734fn test_i32_intFromFloat_f128(a: f128, expected: i32) !void {
735 const x = i32_intFromFloat_f128(a);
720736 try testing.expect(x == expected);
721737}
722738
723fn test__fixunstfsi(a: f128, expected: u32) !void {
724 const x = __fixunstfsi(a);
739fn test_u32_intFromFloat_f128(a: f128, expected: u32) !void {
740 const x = u32_intFromFloat_f128(a);
725741 try testing.expect(x == expected);
726742}
727743
728test "fixtfsi" {
729 try test__fixtfsi(-math.floatMax(f128), math.minInt(i32));
730
731 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
732 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
733
734 try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000);
735 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
736 try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
737
738 try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000);
739 try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000);
740 try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
741 try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
742
743 try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000);
744 try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000);
745
746 try test__fixtfsi(-0x1.000000p+31, -0x80000000);
747 try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
748 try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
749 try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
750
751 try test__fixtfsi(-2.01, -2);
752 try test__fixtfsi(-2.0, -2);
753 try test__fixtfsi(-1.99, -1);
754 try test__fixtfsi(-1.0, -1);
755 try test__fixtfsi(-0.99, 0);
756 try test__fixtfsi(-0.5, 0);
757 try test__fixtfsi(-math.floatMin(f32), 0);
758 try test__fixtfsi(0.0, 0);
759 try test__fixtfsi(math.floatMin(f32), 0);
760 try test__fixtfsi(0.5, 0);
761 try test__fixtfsi(0.99, 0);
762 try test__fixtfsi(1.0, 1);
763 try test__fixtfsi(1.5, 1);
764 try test__fixtfsi(1.99, 1);
765 try test__fixtfsi(2.0, 2);
766 try test__fixtfsi(2.01, 2);
767
768 try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
769 try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
770 try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
771 try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF);
772
773 try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
774 try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
775
776 try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
777 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
778 try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
779 try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
780
781 try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
782 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
783 try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
784
785 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
786 try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
787
788 try test__fixtfsi(math.floatMax(f128), math.maxInt(i32));
744test i32_intFromFloat_f128 {
745 try test_i32_intFromFloat_f128(-math.floatMax(f128), math.minInt(i32));
746
747 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
748 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
749
750 try test_i32_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000);
751 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
752 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
753
754 try test_i32_intFromFloat_f128(-0x1.0000000000001p+63, -0x80000000);
755 try test_i32_intFromFloat_f128(-0x1.0000000000000p+63, -0x80000000);
756 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
757 try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
758
759 try test_i32_intFromFloat_f128(-0x1.FFFFFEp+62, -0x80000000);
760 try test_i32_intFromFloat_f128(-0x1.FFFFFCp+62, -0x80000000);
761
762 try test_i32_intFromFloat_f128(-0x1.000000p+31, -0x80000000);
763 try test_i32_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0);
764 try test_i32_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80);
765 try test_i32_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00);
766
767 try test_i32_intFromFloat_f128(-2.01, -2);
768 try test_i32_intFromFloat_f128(-2.0, -2);
769 try test_i32_intFromFloat_f128(-1.99, -1);
770 try test_i32_intFromFloat_f128(-1.0, -1);
771 try test_i32_intFromFloat_f128(-0.99, 0);
772 try test_i32_intFromFloat_f128(-0.5, 0);
773 try test_i32_intFromFloat_f128(-math.floatMin(f32), 0);
774 try test_i32_intFromFloat_f128(0.0, 0);
775 try test_i32_intFromFloat_f128(math.floatMin(f32), 0);
776 try test_i32_intFromFloat_f128(0.5, 0);
777 try test_i32_intFromFloat_f128(0.99, 0);
778 try test_i32_intFromFloat_f128(1.0, 1);
779 try test_i32_intFromFloat_f128(1.5, 1);
780 try test_i32_intFromFloat_f128(1.99, 1);
781 try test_i32_intFromFloat_f128(2.0, 2);
782 try test_i32_intFromFloat_f128(2.01, 2);
783
784 try test_i32_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00);
785 try test_i32_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80);
786 try test_i32_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0);
787 try test_i32_intFromFloat_f128(0x1.000000p+31, 0x7FFFFFFF);
788
789 try test_i32_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFFFF);
790 try test_i32_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFFFF);
791
792 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
793 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
794 try test_i32_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFF);
795 try test_i32_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFF);
796
797 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
798 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
799 try test_i32_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFF);
800
801 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
802 try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
803
804 try test_i32_intFromFloat_f128(math.floatMax(f128), math.maxInt(i32));
789805}
790806
791test "fixunstfsi" {
792 try test__fixunstfsi(math.inf(f128), 0xffffffff);
793 try test__fixunstfsi(0, 0x0);
794 try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);
795 try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0);
796 try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);
797 try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff);
798 try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff);
799 try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0);
800
801 try test__fixunstfsi(0x1p+32, 0xFFFFFFFF);
807test u32_intFromFloat_f128 {
808 try test_u32_intFromFloat_f128(math.inf(f128), 0xffffffff);
809 try test_u32_intFromFloat_f128(0, 0x0);
810 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+5, 0x24);
811 try test_u32_intFromFloat_f128(0x1.23456789abcdefp-3, 0x0);
812 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+20, 0x123456);
813 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+40, 0xffffffff);
814 try test_u32_intFromFloat_f128(0x1.23456789abcdefp+256, 0xffffffff);
815 try test_u32_intFromFloat_f128(-0x1.23456789abcdefp+3, 0x0);
816
817 try test_u32_intFromFloat_f128(0x1p+32, 0xFFFFFFFF);
802818}
803819
804fn test__fixtfdi(a: f128, expected: i64) !void {
805 const x = __fixtfdi(a);
820fn test_i64_intFromFloat_f128(a: f128, expected: i64) !void {
821 const x = i64_intFromFloat_f128(a);
806822 try testing.expect(x == expected);
807823}
808824
809fn test__fixunstfdi(a: f128, expected: u64) !void {
810 const x = __fixunstfdi(a);
825fn test_u64_intFromFloat_f128(a: f128, expected: u64) !void {
826 const x = u64_intFromFloat_f128(a);
811827 try testing.expect(x == expected);
812828}
813829
814test "fixtfdi" {
815 try test__fixtfdi(-math.floatMax(f128), math.minInt(i64));
816
817 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
818 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
819
820 try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000);
821 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
822 try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
823
824 try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000);
825 try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000);
826 try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
827 try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
828
829 try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
830 try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
831
832 try test__fixtfdi(-0x1.000000p+31, -0x80000000);
833 try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
834 try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80);
835 try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00);
836
837 try test__fixtfdi(-2.01, -2);
838 try test__fixtfdi(-2.0, -2);
839 try test__fixtfdi(-1.99, -1);
840 try test__fixtfdi(-1.0, -1);
841 try test__fixtfdi(-0.99, 0);
842 try test__fixtfdi(-0.5, 0);
843 try test__fixtfdi(-math.floatMin(f64), 0);
844 try test__fixtfdi(0.0, 0);
845 try test__fixtfdi(math.floatMin(f64), 0);
846 try test__fixtfdi(0.5, 0);
847 try test__fixtfdi(0.99, 0);
848 try test__fixtfdi(1.0, 1);
849 try test__fixtfdi(1.5, 1);
850 try test__fixtfdi(1.99, 1);
851 try test__fixtfdi(2.0, 2);
852 try test__fixtfdi(2.01, 2);
853
854 try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00);
855 try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80);
856 try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0);
857 try test__fixtfdi(0x1.000000p+31, 0x80000000);
858
859 try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
860 try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
861
862 try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
863 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
864 try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
865 try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
866
867 try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
868 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
869 try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
870
871 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
872 try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
873
874 try test__fixtfdi(math.floatMax(f128), math.maxInt(i64));
830test i64_intFromFloat_f128 {
831 try test_i64_intFromFloat_f128(-math.floatMax(f128), math.minInt(i64));
832
833 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
834 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
835
836 try test_i64_intFromFloat_f128(-0x1.0000000000000p+127, -0x8000000000000000);
837 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
838 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
839
840 try test_i64_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000000);
841 try test_i64_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000);
842 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
843 try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
844
845 try test_i64_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
846 try test_i64_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
847
848 try test_i64_intFromFloat_f128(-0x1.000000p+31, -0x80000000);
849 try test_i64_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0);
850 try test_i64_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80);
851 try test_i64_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00);
852
853 try test_i64_intFromFloat_f128(-2.01, -2);
854 try test_i64_intFromFloat_f128(-2.0, -2);
855 try test_i64_intFromFloat_f128(-1.99, -1);
856 try test_i64_intFromFloat_f128(-1.0, -1);
857 try test_i64_intFromFloat_f128(-0.99, 0);
858 try test_i64_intFromFloat_f128(-0.5, 0);
859 try test_i64_intFromFloat_f128(-math.floatMin(f64), 0);
860 try test_i64_intFromFloat_f128(0.0, 0);
861 try test_i64_intFromFloat_f128(math.floatMin(f64), 0);
862 try test_i64_intFromFloat_f128(0.5, 0);
863 try test_i64_intFromFloat_f128(0.99, 0);
864 try test_i64_intFromFloat_f128(1.0, 1);
865 try test_i64_intFromFloat_f128(1.5, 1);
866 try test_i64_intFromFloat_f128(1.99, 1);
867 try test_i64_intFromFloat_f128(2.0, 2);
868 try test_i64_intFromFloat_f128(2.01, 2);
869
870 try test_i64_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00);
871 try test_i64_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80);
872 try test_i64_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0);
873 try test_i64_intFromFloat_f128(0x1.000000p+31, 0x80000000);
874
875 try test_i64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
876 try test_i64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
877
878 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
879 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
880 try test_i64_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
881 try test_i64_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
882
883 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
884 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
885 try test_i64_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
886
887 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
888 try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
889
890 try test_i64_intFromFloat_f128(math.floatMax(f128), math.maxInt(i64));
875891}
876892
877test "fixunstfdi" {
878 try test__fixunstfdi(0.0, 0);
879
880 try test__fixunstfdi(0.5, 0);
881 try test__fixunstfdi(0.99, 0);
882 try test__fixunstfdi(1.0, 1);
883 try test__fixunstfdi(1.5, 1);
884 try test__fixunstfdi(1.99, 1);
885 try test__fixunstfdi(2.0, 2);
886 try test__fixunstfdi(2.01, 2);
887 try test__fixunstfdi(-0.5, 0);
888 try test__fixunstfdi(-0.99, 0);
889 try test__fixunstfdi(-1.0, 0);
890 try test__fixunstfdi(-1.5, 0);
891 try test__fixunstfdi(-1.99, 0);
892 try test__fixunstfdi(-2.0, 0);
893 try test__fixunstfdi(-2.01, 0);
894
895 try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
896 try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
897
898 try test__fixunstfdi(-0x1.FFFFFEp+62, 0);
899 try test__fixunstfdi(-0x1.FFFFFCp+62, 0);
900
901 try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
902 try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
903
904 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
905 try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
906
907 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
908 try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
909 try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
910 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
911 try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
912 try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF);
913
914 try test__fixunstfdi(-0x1.0000000000000000p+63, 0);
915 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
916 try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
893test u64_intFromFloat_f128 {
894 try test_u64_intFromFloat_f128(0.0, 0);
895
896 try test_u64_intFromFloat_f128(0.5, 0);
897 try test_u64_intFromFloat_f128(0.99, 0);
898 try test_u64_intFromFloat_f128(1.0, 1);
899 try test_u64_intFromFloat_f128(1.5, 1);
900 try test_u64_intFromFloat_f128(1.99, 1);
901 try test_u64_intFromFloat_f128(2.0, 2);
902 try test_u64_intFromFloat_f128(2.01, 2);
903 try test_u64_intFromFloat_f128(-0.5, 0);
904 try test_u64_intFromFloat_f128(-0.99, 0);
905 try test_u64_intFromFloat_f128(-1.0, 0);
906 try test_u64_intFromFloat_f128(-1.5, 0);
907 try test_u64_intFromFloat_f128(-1.99, 0);
908 try test_u64_intFromFloat_f128(-2.0, 0);
909 try test_u64_intFromFloat_f128(-2.01, 0);
910
911 try test_u64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
912 try test_u64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
913
914 try test_u64_intFromFloat_f128(-0x1.FFFFFEp+62, 0);
915 try test_u64_intFromFloat_f128(-0x1.FFFFFCp+62, 0);
916
917 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
918 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
919
920 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, 0);
921 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, 0);
922
923 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
924 try test_u64_intFromFloat_f128(0x1.0000000000000002p+63, 0x8000000000000001);
925 try test_u64_intFromFloat_f128(0x1.0000000000000000p+63, 0x8000000000000000);
926 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
927 try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
928 try test_u64_intFromFloat_f128(0x1p+64, 0xFFFFFFFFFFFFFFFF);
929
930 try test_u64_intFromFloat_f128(-0x1.0000000000000000p+63, 0);
931 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
932 try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
917933}
918934
919fn test__fixtfti(a: f128, expected: i128) !void {
920 const x = __fixtfti(a);
935fn test_i128_intFromFloat_f128(a: f128, expected: i128) !void {
936 const x = i128_intFromFloat_f128(a);
921937 try testing.expect(x == expected);
922938}
923939
924fn test__fixunstfti(a: f128, expected: u128) !void {
925 const x = __fixunstfti(a);
940fn test_u128_intFromFloat_f128(a: f128, expected: u128) !void {
941 const x = u128_intFromFloat_f128(a);
926942 try testing.expect(x == expected);
927943}
928944
929test "fixtfti" {
930 try test__fixtfti(-math.floatMax(f128), math.minInt(i128));
931
932 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
933 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
934
935 try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
936 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
937 try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
938
939 try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);
940 try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);
941 try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
942 try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
943
944 try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
945 try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
946
947 try test__fixtfti(-2.01, -2);
948 try test__fixtfti(-2.0, -2);
949 try test__fixtfti(-1.99, -1);
950 try test__fixtfti(-1.0, -1);
951 try test__fixtfti(-0.99, 0);
952 try test__fixtfti(-0.5, 0);
953 try test__fixtfti(-math.floatMin(f128), 0);
954 try test__fixtfti(0.0, 0);
955 try test__fixtfti(math.floatMin(f128), 0);
956 try test__fixtfti(0.5, 0);
957 try test__fixtfti(0.99, 0);
958 try test__fixtfti(1.0, 1);
959 try test__fixtfti(1.5, 1);
960 try test__fixtfti(1.99, 1);
961 try test__fixtfti(2.0, 2);
962 try test__fixtfti(2.01, 2);
963
964 try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
965 try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
966
967 try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
968 try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
969 try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);
970 try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);
971
972 try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
973 try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
974 try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
975
976 try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
977 try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
978
979 try test__fixtfti(math.floatMax(f128), math.maxInt(i128));
945test i128_intFromFloat_f128 {
946 try test_i128_intFromFloat_f128(-math.floatMax(f128), math.minInt(i128));
947
948 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
949 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
950
951 try test_i128_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
952 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
953 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
954
955 try test_i128_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000800);
956 try test_i128_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000);
957 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
958 try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
959
960 try test_i128_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7fffff8000000000);
961 try test_i128_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7fffff0000000000);
962
963 try test_i128_intFromFloat_f128(-2.01, -2);
964 try test_i128_intFromFloat_f128(-2.0, -2);
965 try test_i128_intFromFloat_f128(-1.99, -1);
966 try test_i128_intFromFloat_f128(-1.0, -1);
967 try test_i128_intFromFloat_f128(-0.99, 0);
968 try test_i128_intFromFloat_f128(-0.5, 0);
969 try test_i128_intFromFloat_f128(-math.floatMin(f128), 0);
970 try test_i128_intFromFloat_f128(0.0, 0);
971 try test_i128_intFromFloat_f128(math.floatMin(f128), 0);
972 try test_i128_intFromFloat_f128(0.5, 0);
973 try test_i128_intFromFloat_f128(0.99, 0);
974 try test_i128_intFromFloat_f128(1.0, 1);
975 try test_i128_intFromFloat_f128(1.5, 1);
976 try test_i128_intFromFloat_f128(1.99, 1);
977 try test_i128_intFromFloat_f128(2.0, 2);
978 try test_i128_intFromFloat_f128(2.01, 2);
979
980 try test_i128_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
981 try test_i128_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
982
983 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
984 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
985 try test_i128_intFromFloat_f128(0x1.0000000000000p+63, 0x8000000000000000);
986 try test_i128_intFromFloat_f128(0x1.0000000000001p+63, 0x8000000000000800);
987
988 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
989 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
990 try test_i128_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
991
992 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
993 try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
994
995 try test_i128_intFromFloat_f128(math.floatMax(f128), math.maxInt(i128));
980996}
981997
982test "fixunstfti" {
983 try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff);
998test u128_intFromFloat_f128 {
999 try test_u128_intFromFloat_f128(math.inf(f128), 0xffffffffffffffffffffffffffffffff);
9841000
985 try test__fixunstfti(0.0, 0);
1001 try test_u128_intFromFloat_f128(0.0, 0);
9861002
987 try test__fixunstfti(0.5, 0);
988 try test__fixunstfti(0.99, 0);
989 try test__fixunstfti(1.0, 1);
990 try test__fixunstfti(1.5, 1);
991 try test__fixunstfti(1.99, 1);
992 try test__fixunstfti(2.0, 2);
993 try test__fixunstfti(2.01, 2);
994 try test__fixunstfti(-0.01, 0);
995 try test__fixunstfti(-0.99, 0);
1003 try test_u128_intFromFloat_f128(0.5, 0);
1004 try test_u128_intFromFloat_f128(0.99, 0);
1005 try test_u128_intFromFloat_f128(1.0, 1);
1006 try test_u128_intFromFloat_f128(1.5, 1);
1007 try test_u128_intFromFloat_f128(1.99, 1);
1008 try test_u128_intFromFloat_f128(2.0, 2);
1009 try test_u128_intFromFloat_f128(2.01, 2);
1010 try test_u128_intFromFloat_f128(-0.01, 0);
1011 try test_u128_intFromFloat_f128(-0.99, 0);
9961012
997 try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff);
1013 try test_u128_intFromFloat_f128(0x1p+128, 0xffffffffffffffffffffffffffffffff);
9981014
999 try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000);
1000 try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000);
1001 try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff);
1002 try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff);
1015 try test_u128_intFromFloat_f128(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000);
1016 try test_u128_intFromFloat_f128(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000);
1017 try test_u128_intFromFloat_f128(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff);
1018 try test_u128_intFromFloat_f128(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff);
10031019}
10041020
1005fn test__fixunshfti(a: f16, expected: u128) !void {
1006 const x = __fixunshfti(a);
1021fn test_u128_intFromFloat_f16(a: f16, expected: u128) !void {
1022 const x = impl.u128_intFromFloat_f16(a);
10071023 try testing.expect(x == expected);
10081024}
10091025
1010test "fixunshfti for f16" {
1011 try test__fixunshfti(math.inf(f16), math.maxInt(u128));
1012 try test__fixunshfti(math.floatMax(f16), 65504);
1026test u128_intFromFloat_f16 {
1027 try test_u128_intFromFloat_f16(math.inf(f16), math.maxInt(u128));
1028 try test_u128_intFromFloat_f16(math.floatMax(f16), 65504);
10131029}
10141030
1015fn test__fixunsxfti(a: f80, expected: u128) !void {
1016 const x = __fixunsxfti(a);
1031fn test_u128_intFromFloat_f80(a: f80, expected: u128) !void {
1032 const x = impl.u128_intFromFloat_f80(a);
10171033 try testing.expect(x == expected);
10181034}
10191035
1020test "fixunsxfti for f80" {
1021 try test__fixunsxfti(math.inf(f80), math.maxInt(u128));
1022 try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128));
1023 try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64));
1036test u128_intFromFloat_f80 {
1037 try test_u128_intFromFloat_f80(math.inf(f80), math.maxInt(u128));
1038 try test_u128_intFromFloat_f80(math.floatMax(f80), math.maxInt(u128));
1039 try test_u128_intFromFloat_f80(math.maxInt(u64), math.maxInt(u64));
10241040}
lib/compiler_rt/limb64.zig+1-1
......@@ -6,7 +6,7 @@ const minInt = std.math.minInt;
66
77const builtin = @import("builtin");
88const compiler_rt = @import("../compiler_rt.zig");
9const symbol = @import("../compiler_rt.zig").symbol;
9const symbol = compiler_rt.symbol;
1010
1111const endian = builtin.cpu.arch.endian();
1212
lib/compiler_rt/log.zig+113-101
......@@ -11,26 +11,29 @@ const expectEqual = std.testing.expectEqual;
1111const expectApproxEqRel = std.testing.expectApproxEqRel;
1212
1313const compiler_rt = @import("../compiler_rt.zig");
14const symbol = @import("../compiler_rt.zig").symbol;
14const symbol = compiler_rt.symbol;
1515
1616comptime {
1717 symbol(&__logh, "__logh");
1818 symbol(&logf, "logf");
1919 symbol(&log, "log");
2020 symbol(&__logx, "__logx");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&logq, "logf128");
23 }
24 symbol(&logq, "logq");
21 symbol(&logq, "logf128");
2522 symbol(&logl, "logl");
2623}
2724
28pub fn __logh(a: f16) callconv(.c) f16 {
25fn __logh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
26 return compiler_rt.f16.toAbi(log_f16(compiler_rt.f16.fromAbi(a)));
27}
28pub fn log_f16(a: f16) f16 {
2929 // TODO: more efficient implementation
30 return @floatCast(logf(a));
30 return @floatCast(log_f32(a));
3131}
3232
33pub fn logf(x_: f32) callconv(.c) f32 {
33fn logf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
34 return compiler_rt.f32.toAbi(log_f32(compiler_rt.f32.fromAbi(a)));
35}
36pub fn log_f32(x_: f32) f32 {
3437 const ln2_hi: f32 = 6.9313812256e-01;
3538 const ln2_lo: f32 = 9.0580006145e-06;
3639 const Lg1: f32 = 0xaaaaaa.0p-24;
......@@ -82,7 +85,10 @@ pub fn logf(x_: f32) callconv(.c) f32 {
8285 return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
8386}
8487
85pub fn log(x: f64) callconv(.c) f64 {
88fn log(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
89 return compiler_rt.f64.toAbi(log_f64(compiler_rt.f64.fromAbi(a)));
90}
91pub fn log_f64(x: f64) f64 {
8692 const poly1 = [_]f64{
8793 -0x1p-1,
8894 0x1.5555555555577p-2,
......@@ -432,11 +438,17 @@ pub fn log(x: f64) callconv(.c) f64 {
432438 return @bitCast(y);
433439}
434440
435pub fn __logx(a: f80) callconv(.c) f80 {
441fn __logx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
442 return compiler_rt.f80.toAbi(log_f80(compiler_rt.f80.fromAbi(a)));
443}
444pub fn log_f80(a: f80) f80 {
436445 // TODO: more efficient implementation
437 return @floatCast(logq(a));
446 return @floatCast(log_f128(a));
438447}
439448
449fn logq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
450 return compiler_rt.f128.toAbi(log_f128(compiler_rt.f128.fromAbi(a)));
451}
440452/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
441453/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
442454///
......@@ -449,7 +461,7 @@ pub fn __logx(a: f80) callconv(.c) f80 {
449461///
450462/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
451463/// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp
452pub fn logq(x: f128) callconv(.c) f128 {
464pub fn log_f128(x: f128) f128 {
453465 const impl = @import("log_f128.zig");
454466
455467 if (impl.specialCases(x)) |y|
......@@ -626,123 +638,123 @@ pub fn logq(x: f128) callconv(.c) f128 {
626638
627639pub fn logl(x: c_longdouble) callconv(.c) c_longdouble {
628640 switch (@typeInfo(c_longdouble).float.bits) {
629 64 => return log(x),
630 80 => return __logx(x),
631 128 => return logq(x),
632 else => @compileError("unreachable"),
641 64 => return log_f64(x),
642 80 => return log_f80(x),
643 128 => return log_f128(x),
644 else => comptime unreachable,
633645 }
634646}
635647
636648test "logf() special" {
637 try expectEqual(logf(0.0), -math.inf(f32));
638 try expectEqual(logf(-0.0), -math.inf(f32));
639 try expect(math.isPositiveZero(logf(1.0)));
640 try expectEqual(logf(math.e), 1.0);
641 try expectEqual(logf(math.inf(f32)), math.inf(f32));
642 try expect(math.isNan(logf(-1.0)));
643 try expect(math.isNan(logf(-math.inf(f32))));
644 try expect(math.isNan(logf(math.nan(f32))));
645 try expect(math.isNan(logf(math.snan(f32))));
649 try expectEqual(log_f32(0.0), -math.inf(f32));
650 try expectEqual(log_f32(-0.0), -math.inf(f32));
651 try expect(math.isPositiveZero(log_f32(1.0)));
652 try expectEqual(log_f32(math.e), 1.0);
653 try expectEqual(log_f32(math.inf(f32)), math.inf(f32));
654 try expect(math.isNan(log_f32(-1.0)));
655 try expect(math.isNan(log_f32(-math.inf(f32))));
656 try expect(math.isNan(log_f32(math.nan(f32))));
657 try expect(math.isNan(log_f32(math.snan(f32))));
646658}
647659
648660test "logf() sanity" {
649 try expect(math.isNan(logf(-0x1.0223a0p+3)));
650 try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0);
651 try expect(math.isNan(logf(-0x1.0c34b4p+3)));
652 try expect(math.isNan(logf(-0x1.a206f0p+2)));
653 try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1);
654 try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2);
655 try expect(math.isNan(logf(-0x1.a05cc8p-2)));
656 try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1);
657 try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2);
658 try expect(math.isNan(logf(-0x1.5b86eap-1)));
661 try expect(math.isNan(log_f32(-0x1.0223a0p+3)));
662 try expectEqual(log_f32(0x1.161868p+2), 0x1.7815b0p+0);
663 try expect(math.isNan(log_f32(-0x1.0c34b4p+3)));
664 try expect(math.isNan(log_f32(-0x1.a206f0p+2)));
665 try expectEqual(log_f32(0x1.288bbcp+3), 0x1.1cfcd6p+1);
666 try expectEqual(log_f32(0x1.52efd0p-1), -0x1.a6694cp-2);
667 try expect(math.isNan(log_f32(-0x1.a05cc8p-2)));
668 try expectEqual(log_f32(0x1.1f9efap-1), -0x1.2742bap-1);
669 try expectEqual(log_f32(0x1.8c5db0p-1), -0x1.062160p-2);
670 try expect(math.isNan(log_f32(-0x1.5b86eap-1)));
659671}
660672
661673test "logf() boundary" {
662 try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
663 try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
664 try expect(math.isNan(logf(-0x1p-149))); // Min negative input value
665 try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0
666 try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
667 try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal
668 try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal
674 try expectEqual(log_f32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value
675 try expectEqual(log_f32(0x1p-149), -0x1.9d1da0p+6); // Min positive input value
676 try expect(math.isNan(log_f32(-0x1p-149))); // Min negative input value
677 try expectEqual(log_f32(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0
678 try expectEqual(log_f32(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0
679 try expectEqual(log_f32(0x1p-126), -0x1.5d58a0p+6); // First subnormal
680 try expect(math.isNan(log_f32(-0x1p-126))); // First negative subnormal
669681}
670682
671683test "log() special" {
672 try expectEqual(log(0.0), -math.inf(f64));
673 try expectEqual(log(-0.0), -math.inf(f64));
674 try expect(math.isPositiveZero(log(1.0)));
675 try expectEqual(log(math.e), 1.0);
676 try expectEqual(log(math.inf(f64)), math.inf(f64));
677 try expect(math.isNan(log(-1.0)));
678 try expect(math.isNan(log(-math.inf(f64))));
679 try expect(math.isNan(log(math.nan(f64))));
680 try expect(math.isNan(log(math.snan(f64))));
684 try expectEqual(log_f64(0.0), -math.inf(f64));
685 try expectEqual(log_f64(-0.0), -math.inf(f64));
686 try expect(math.isPositiveZero(log_f64(1.0)));
687 try expectEqual(log_f64(math.e), 1.0);
688 try expectEqual(log_f64(math.inf(f64)), math.inf(f64));
689 try expect(math.isNan(log_f64(-1.0)));
690 try expect(math.isNan(log_f64(-math.inf(f64))));
691 try expect(math.isNan(log_f64(math.nan(f64))));
692 try expect(math.isNan(log_f64(math.snan(f64))));
681693}
682694
683695test "log() sanity" {
684 try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3)));
685 try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
686 try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3)));
687 try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2)));
688 try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
689 try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
690 try expect(math.isNan(log(-0x1.a05cc754481d1p-2)));
691 try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
692 try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
693 try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1)));
696 try expect(math.isNan(log_f64(-0x1.02239f3c6a8f1p+3)));
697 try expectEqual(log_f64(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0);
698 try expect(math.isNan(log_f64(-0x1.0c34b3e01e6e7p+3)));
699 try expect(math.isNan(log_f64(-0x1.a206f0a19dcc4p+2)));
700 try expectEqual(log_f64(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1);
701 try expectEqual(log_f64(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2);
702 try expect(math.isNan(log_f64(-0x1.a05cc754481d1p-2)));
703 try expectEqual(log_f64(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1);
704 try expectEqual(log_f64(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2);
705 try expect(math.isNan(log_f64(-0x1.5b86ea8118a0ep-1)));
694706}
695707
696708test "log() boundary" {
697 try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
698 try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
699 try expect(math.isNan(log(-0x1p-1074))); // Min negative input value
700 try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0
701 try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
702 try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
703 try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal
709 try expectEqual(log_f64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value
710 try expectEqual(log_f64(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value
711 try expect(math.isNan(log_f64(-0x1p-1074))); // Min negative input value
712 try expectEqual(log_f64(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0
713 try expectEqual(log_f64(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0
714 try expectEqual(log_f64(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal
715 try expect(math.isNan(log_f64(-0x1p-1022))); // First negative subnormal
704716}
705717
706718test "logq() special" {
707 try expectEqual(logq(0.0), -math.inf(f128));
708 try expectEqual(logq(-0.0), -math.inf(f128));
709 try expect(math.isPositiveZero(logq(1.0)));
719 try expectEqual(log_f128(0.0), -math.inf(f128));
720 try expectEqual(log_f128(-0.0), -math.inf(f128));
721 try expect(math.isPositiveZero(log_f128(1.0)));
710722 // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999
711 // is the correctly rounded value of logq(math.e)
712 try expectApproxEqRel(logq(math.e), 1.0, math.floatEpsAt(f128, 1.0));
713 try expectEqual(logq(math.inf(f128)), math.inf(f128));
714 try expect(math.isNan(logq(-1.0)));
715 try expect(math.isNan(logq(-math.inf(f128))));
716 try expect(math.isNan(logq(math.nan(f128))));
717 try expect(math.isNan(logq(math.snan(f128))));
723 // is the correctly rounded value of log_f128(math.e)
724 try expectApproxEqRel(log_f128(math.e), 1.0, math.floatEpsAt(f128, 1.0));
725 try expectEqual(log_f128(math.inf(f128)), math.inf(f128));
726 try expect(math.isNan(log_f128(-1.0)));
727 try expect(math.isNan(log_f128(-math.inf(f128))));
728 try expect(math.isNan(log_f128(math.nan(f128))));
729 try expect(math.isNan(log_f128(math.snan(f128))));
718730}
719731
720732test "logq() boundary" {
721 try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value
722 try expectEqual(logq(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value
723 try expect(math.isNan(logq(-0x1p-16494))); // Min negative input value
724 try expectEqual(logq(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0
725 try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0
726 try expectEqual(logq(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal
727 try expect(math.isNan(logq(-0x1p-16382))); // First negative subnormal
733 try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value
734 try expectEqual(log_f128(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value
735 try expect(math.isNan(log_f128(-0x1p-16494))); // Min negative input value
736 try expectEqual(log_f128(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0
737 try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0
738 try expectEqual(log_f128(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal
739 try expect(math.isNan(log_f128(-0x1p-16382))); // First negative subnormal
728740}
729741
730742test "logq() sanity" {
731 try expectEqual(logq(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0);
732 try expectEqual(logq(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1);
733 try expectEqual(logq(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1);
734 try expectEqual(logq(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1);
735 try expectEqual(logq(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1);
736 try expectEqual(logq(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1);
737 try expectEqual(logq(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1);
738 try expectEqual(logq(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1);
739 try expectEqual(logq(1.200355637363589375e14), 3.2418809179272977400408325788186897e1);
740 try expectEqual(logq(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1);
741 try expectEqual(logq(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1);
743 try expectEqual(log_f128(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0);
744 try expectEqual(log_f128(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1);
745 try expectEqual(log_f128(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1);
746 try expectEqual(log_f128(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1);
747 try expectEqual(log_f128(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1);
748 try expectEqual(log_f128(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1);
749 try expectEqual(log_f128(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1);
750 try expectEqual(log_f128(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1);
751 try expectEqual(log_f128(1.200355637363589375e14), 3.2418809179272977400408325788186897e1);
752 try expectEqual(log_f128(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1);
753 try expectEqual(log_f128(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1);
742754 // testing near 1
743 try expectEqual(logq(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2);
744 try expectEqual(logq(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2);
745 try expectEqual(logq(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2);
746 try expectEqual(logq(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2);
747 try expectEqual(logq(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2);
755 try expectEqual(log_f128(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2);
756 try expectEqual(log_f128(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2);
757 try expectEqual(log_f128(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2);
758 try expectEqual(log_f128(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2);
759 try expectEqual(log_f128(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2);
748760}
lib/compiler_rt/log10.zig+114-102
......@@ -18,19 +18,22 @@ comptime {
1818 symbol(&log10f, "log10f");
1919 symbol(&log10, "log10");
2020 symbol(&__log10x, "__log10x");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&log10q, "log10f128");
23 }
24 symbol(&log10q, "log10q");
21 symbol(&log10q, "log10f128");
2522 symbol(&log10l, "log10l");
2623}
2724
28pub fn __log10h(a: f16) callconv(.c) f16 {
25fn __log10h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
26 return compiler_rt.f16.toAbi(log10_f16(compiler_rt.f16.fromAbi(a)));
27}
28pub fn log10_f16(a: f16) f16 {
2929 // TODO: more efficient implementation
30 return @floatCast(log10f(a));
30 return @floatCast(log10_f32(a));
3131}
3232
33pub fn log10f(x_: f32) callconv(.c) f32 {
33fn log10f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
34 return compiler_rt.f32.toAbi(log10_f32(compiler_rt.f32.fromAbi(a)));
35}
36pub fn log10_f32(x_: f32) f32 {
3437 const ivln10hi: f32 = 4.3432617188e-01;
3538 const ivln10lo: f32 = -3.1689971365e-05;
3639 const log10_2hi: f32 = 3.0102920532e-01;
......@@ -90,7 +93,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 {
9093 return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
9194}
9295
93pub fn log10(x_: f64) callconv(.c) f64 {
96fn log10(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
97 return compiler_rt.f64.toAbi(log10_f64(compiler_rt.f64.fromAbi(a)));
98}
99pub fn log10_f64(x_: f64) f64 {
94100 const ivln10hi: f64 = 4.34294481878168880939e-01;
95101 const ivln10lo: f64 = 2.50829467116452752298e-11;
96102 const log10_2hi: f64 = 3.01029995663611771306e-01;
......@@ -165,11 +171,17 @@ pub fn log10(x_: f64) callconv(.c) f64 {
165171 return val_lo + val_hi;
166172}
167173
168pub fn __log10x(a: f80) callconv(.c) f80 {
174fn __log10x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
175 return compiler_rt.f80.toAbi(log10_f80(compiler_rt.f80.fromAbi(a)));
176}
177pub fn log10_f80(a: f80) f80 {
169178 // TODO: more efficient implementation
170 return @floatCast(log10q(a));
179 return @floatCast(log10_f128(a));
171180}
172181
182fn log10q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
183 return compiler_rt.f128.toAbi(log10_f128(compiler_rt.f128.fromAbi(a)));
184}
173185/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
174186/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
175187///
......@@ -182,7 +194,7 @@ pub fn __log10x(a: f80) callconv(.c) f80 {
182194///
183195/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
184196/// <= 0.5 ulp: 99.96%, worst case <= 0.565 ulp
185pub fn log10q(x: f128) callconv(.c) f128 {
197pub fn log10_f128(x: f128) f128 {
186198 const impl = @import("log_f128.zig");
187199
188200 if (impl.specialCases(x)) |y|
......@@ -359,124 +371,124 @@ pub fn log10q(x: f128) callconv(.c) f128 {
359371
360372pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble {
361373 switch (@typeInfo(c_longdouble).float.bits) {
362 64 => return log10(x),
363 80 => return __log10x(x),
364 128 => return log10q(x),
365 else => @compileError("unreachable"),
374 64 => return log10_f64(x),
375 80 => return log10_f80(x),
376 128 => return log10_f128(x),
377 else => comptime unreachable,
366378 }
367379}
368380
369381test "log10f() special" {
370 try expectEqual(log10f(0.0), -math.inf(f32));
371 try expectEqual(log10f(-0.0), -math.inf(f32));
372 try expect(math.isPositiveZero(log10f(1.0)));
373 try expectEqual(log10f(10.0), 1.0);
374 try expectEqual(log10f(0.1), -1.0);
375 try expectEqual(log10f(math.inf(f32)), math.inf(f32));
376 try expect(math.isNan(log10f(-1.0)));
377 try expect(math.isNan(log10f(-math.inf(f32))));
378 try expect(math.isNan(log10f(math.nan(f32))));
379 try expect(math.isNan(log10f(math.snan(f32))));
382 try expectEqual(log10_f32(0.0), -math.inf(f32));
383 try expectEqual(log10_f32(-0.0), -math.inf(f32));
384 try expect(math.isPositiveZero(log10_f32(1.0)));
385 try expectEqual(log10_f32(10.0), 1.0);
386 try expectEqual(log10_f32(0.1), -1.0);
387 try expectEqual(log10_f32(math.inf(f32)), math.inf(f32));
388 try expect(math.isNan(log10_f32(-1.0)));
389 try expect(math.isNan(log10_f32(-math.inf(f32))));
390 try expect(math.isNan(log10_f32(math.nan(f32))));
391 try expect(math.isNan(log10_f32(math.snan(f32))));
380392}
381393
382394test "log10f() sanity" {
383 try expect(math.isNan(log10f(-0x1.0223a0p+3)));
384 try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1);
385 try expect(math.isNan(log10f(-0x1.0c34b4p+3)));
386 try expect(math.isNan(log10f(-0x1.a206f0p+2)));
387 try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1);
388 try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
389 try expect(math.isNan(log10f(-0x1.a05cc8p-2)));
390 try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2);
391 try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4);
392 try expect(math.isNan(log10f(-0x1.5b86eap-1)));
395 try expect(math.isNan(log10_f32(-0x1.0223a0p+3)));
396 try expectEqual(log10_f32(0x1.161868p+2), 0x1.46a9bcp-1);
397 try expect(math.isNan(log10_f32(-0x1.0c34b4p+3)));
398 try expect(math.isNan(log10_f32(-0x1.a206f0p+2)));
399 try expectEqual(log10_f32(0x1.288bbcp+3), 0x1.ef1300p-1);
400 try expectEqual(log10_f32(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit
401 try expect(math.isNan(log10_f32(-0x1.a05cc8p-2)));
402 try expectEqual(log10_f32(0x1.1f9efap-1), -0x1.0075ccp-2);
403 try expectEqual(log10_f32(0x1.8c5db0p-1), -0x1.c75df8p-4);
404 try expect(math.isNan(log10_f32(-0x1.5b86eap-1)));
393405}
394406
395407test "log10f() boundary" {
396 try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value
397 try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
398 try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value
399 try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0
400 try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
401 try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal
402 try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal
408 try expectEqual(log10_f32(0x1.fffffep+127), 0x1.344136p+5); // Max input value
409 try expectEqual(log10_f32(0x1p-149), -0x1.66d3e8p+5); // Min positive input value
410 try expect(math.isNan(log10_f32(-0x1p-149))); // Min negative input value
411 try expectEqual(log10_f32(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0
412 try expectEqual(log10_f32(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0
413 try expectEqual(log10_f32(0x1p-126), -0x1.2f7030p+5); // First subnormal
414 try expect(math.isNan(log10_f32(-0x1p-126))); // First negative subnormal
403415}
404416
405417test "log10() special" {
406 try expectEqual(log10(0.0), -math.inf(f64));
407 try expectEqual(log10(-0.0), -math.inf(f64));
408 try expect(math.isPositiveZero(log10(1.0)));
409 try expectEqual(log10(10.0), 1.0);
410 try expectEqual(log10(0.1), -1.0);
411 try expectEqual(log10(math.inf(f64)), math.inf(f64));
412 try expect(math.isNan(log10(-1.0)));
413 try expect(math.isNan(log10(-math.inf(f64))));
414 try expect(math.isNan(log10(math.nan(f64))));
415 try expect(math.isNan(log10(math.snan(f64))));
418 try expectEqual(log10_f64(0.0), -math.inf(f64));
419 try expectEqual(log10_f64(-0.0), -math.inf(f64));
420 try expect(math.isPositiveZero(log10_f64(1.0)));
421 try expectEqual(log10_f64(10.0), 1.0);
422 try expectEqual(log10_f64(0.1), -1.0);
423 try expectEqual(log10_f64(math.inf(f64)), math.inf(f64));
424 try expect(math.isNan(log10_f64(-1.0)));
425 try expect(math.isNan(log10_f64(-math.inf(f64))));
426 try expect(math.isNan(log10_f64(math.nan(f64))));
427 try expect(math.isNan(log10_f64(math.snan(f64))));
416428}
417429
418430test "log10() sanity" {
419 try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3)));
420 try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
421 try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3)));
422 try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2)));
423 try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
424 try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
425 try expect(math.isNan(log10(-0x1.a05cc754481d1p-2)));
426 try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
427 try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
428 try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1)));
431 try expect(math.isNan(log10_f64(-0x1.02239f3c6a8f1p+3)));
432 try expectEqual(log10_f64(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1);
433 try expect(math.isNan(log10_f64(-0x1.0c34b3e01e6e7p+3)));
434 try expect(math.isNan(log10_f64(-0x1.a206f0a19dcc4p+2)));
435 try expectEqual(log10_f64(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1);
436 try expectEqual(log10_f64(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3);
437 try expect(math.isNan(log10_f64(-0x1.a05cc754481d1p-2)));
438 try expectEqual(log10_f64(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2);
439 try expectEqual(log10_f64(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4);
440 try expect(math.isNan(log10_f64(-0x1.5b86ea8118a0ep-1)));
429441}
430442
431443test "log10() boundary" {
432 try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
433 try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
434 try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value
435 try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0
436 try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
437 try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
438 try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal
444 try expectEqual(log10_f64(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value
445 try expectEqual(log10_f64(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value
446 try expect(math.isNan(log10_f64(-0x1p-1074))); // Min negative input value
447 try expectEqual(log10_f64(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0
448 try expectEqual(log10_f64(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0
449 try expectEqual(log10_f64(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal
450 try expect(math.isNan(log10_f64(-0x1p-1022))); // First negative subnormal
439451}
440452
441453test "log10q() special" {
442 try expectEqual(log10q(0.0), -math.inf(f128));
443 try expectEqual(log10q(-0.0), -math.inf(f128));
444 try expect(math.isPositiveZero(log10q(1.0)));
445 try expectEqual(log10q(10.0), 1.0);
446 try expectEqual(log10q(0.1), -1.0);
447 try expectEqual(log10q(math.inf(f128)), math.inf(f128));
448 try expect(math.isNan(log10q(-1.0)));
449 try expect(math.isNan(log10q(-math.inf(f128))));
450 try expect(math.isNan(log10q(math.nan(f128))));
451 try expect(math.isNan(log10q(math.snan(f128))));
454 try expectEqual(log10_f128(0.0), -math.inf(f128));
455 try expectEqual(log10_f128(-0.0), -math.inf(f128));
456 try expect(math.isPositiveZero(log10_f128(1.0)));
457 try expectEqual(log10_f128(10.0), 1.0);
458 try expectEqual(log10_f128(0.1), -1.0);
459 try expectEqual(log10_f128(math.inf(f128)), math.inf(f128));
460 try expect(math.isNan(log10_f128(-1.0)));
461 try expect(math.isNan(log10_f128(-math.inf(f128))));
462 try expect(math.isNan(log10_f128(math.nan(f128))));
463 try expect(math.isNan(log10_f128(math.snan(f128))));
452464}
453465
454466test "log10q() sanity" {
455 try expectEqual(log10q(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3);
456 try expectEqual(log10q(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3);
457 try expectEqual(log10q(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2);
458 try expectEqual(log10q(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3);
459 try expectEqual(log10q(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3);
460 try expectEqual(log10q(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3);
461 try expectEqual(log10q(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3);
462 try expectEqual(log10q(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3);
463 try expectEqual(log10q(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3);
464 try expectEqual(log10q(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2);
467 try expectEqual(log10_f128(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3);
468 try expectEqual(log10_f128(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3);
469 try expectEqual(log10_f128(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2);
470 try expectEqual(log10_f128(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3);
471 try expectEqual(log10_f128(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3);
472 try expectEqual(log10_f128(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3);
473 try expectEqual(log10_f128(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3);
474 try expectEqual(log10_f128(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3);
475 try expectEqual(log10_f128(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3);
476 try expectEqual(log10_f128(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2);
465477 // testing near 1
466 try expectEqual(log10q(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2);
467 try expectEqual(log10q(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2);
468 try expectEqual(log10q(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3);
469 try expectEqual(log10q(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2);
470 try expectEqual(log10q(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3);
471 try expectEqual(log10q(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2);
478 try expectEqual(log10_f128(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2);
479 try expectEqual(log10_f128(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2);
480 try expectEqual(log10_f128(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3);
481 try expectEqual(log10_f128(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2);
482 try expectEqual(log10_f128(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3);
483 try expectEqual(log10_f128(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2);
472484}
473485
474486test "log10q() boundary" {
475 try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value
476 try expectEqual(log10q(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value
477 try expect(math.isNan(log10q(-0x1p-16494))); // Min negative input value
478 try expectEqual(log10q(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0
479 try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0
480 try expectEqual(log10q(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal
481 try expect(math.isNan(log10q(-0x1p-16382))); // First negative subnormal
487 try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value
488 try expectEqual(log10_f128(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value
489 try expect(math.isNan(log10_f128(-0x1p-16494))); // Min negative input value
490 try expectEqual(log10_f128(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0
491 try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0
492 try expectEqual(log10_f128(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal
493 try expect(math.isNan(log10_f128(-0x1p-16382))); // First negative subnormal
482494}
lib/compiler_rt/log2.zig+106-94
......@@ -19,19 +19,22 @@ comptime {
1919 symbol(&log2f, "log2f");
2020 symbol(&log2, "log2");
2121 symbol(&__log2x, "__log2x");
22 if (compiler_rt.want_ppc_abi) {
23 symbol(&log2q, "log2f128");
24 }
25 symbol(&log2q, "log2q");
22 symbol(&log2q, "log2f128");
2623 symbol(&log2l, "log2l");
2724}
2825
29pub fn __log2h(a: f16) callconv(.c) f16 {
26fn __log2h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
27 return compiler_rt.f16.toAbi(log2_f16(compiler_rt.f16.fromAbi(a)));
28}
29pub fn log2_f16(a: f16) f16 {
3030 // TODO: more efficient implementation
31 return @floatCast(log2f(a));
31 return @floatCast(log2_f32(a));
3232}
3333
34pub fn log2f(x_: f32) callconv(.c) f32 {
34fn log2f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
35 return compiler_rt.f32.toAbi(log2_f32(compiler_rt.f32.fromAbi(a)));
36}
37pub fn log2_f32(x_: f32) f32 {
3538 const ivln2hi: f32 = 1.4428710938e+00;
3639 const ivln2lo: f32 = -1.7605285393e-04;
3740 const Lg1: f32 = 0xaaaaaa.0p-24;
......@@ -87,7 +90,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 {
8790 return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k));
8891}
8992
90pub fn log2(x_: f64) callconv(.c) f64 {
93fn log2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
94 return compiler_rt.f64.toAbi(log2_f64(compiler_rt.f64.fromAbi(a)));
95}
96pub fn log2_f64(x_: f64) f64 {
9197 const ivln2hi: f64 = 1.44269504072144627571e+00;
9298 const ivln2lo: f64 = 1.67517131648865118353e-10;
9399 const Lg1: f64 = 6.666666666666735130e-01;
......@@ -158,11 +164,17 @@ pub fn log2(x_: f64) callconv(.c) f64 {
158164 return val_lo + val_hi;
159165}
160166
161pub fn __log2x(a: f80) callconv(.c) f80 {
167fn __log2x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
168 return compiler_rt.f80.toAbi(log2_f80(compiler_rt.f80.fromAbi(a)));
169}
170pub fn log2_f80(a: f80) f80 {
162171 // TODO: more efficient implementation
163 return @floatCast(log2q(a));
172 return @floatCast(log2_f128(a));
164173}
165174
175fn log2q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
176 return compiler_rt.f128.toAbi(log2_f128(compiler_rt.f128.fromAbi(a)));
177}
166178/// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic"
167179/// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990
168180///
......@@ -175,7 +187,7 @@ pub fn __log2x(a: f80) callconv(.c) f80 {
175187///
176188/// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case):
177189/// <= 0.5 ulp: 99.86%, worst case <= 0.546 ulp
178pub fn log2q(x: f128) callconv(.c) f128 {
190pub fn log2_f128(x: f128) f128 {
179191 const impl = @import("log_f128.zig");
180192
181193 if (impl.specialCases(x)) |y|
......@@ -351,117 +363,117 @@ pub fn log2q(x: f128) callconv(.c) f128 {
351363
352364pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble {
353365 switch (@typeInfo(c_longdouble).float.bits) {
354 64 => return log2(x),
355 80 => return __log2x(x),
356 128 => return log2q(x),
357 else => @compileError("unreachable"),
366 64 => return log2_f64(x),
367 80 => return log2_f80(x),
368 128 => return log2_f128(x),
369 else => comptime unreachable,
358370 }
359371}
360372
361373test "log2f() special" {
362 try expectEqual(log2f(0.0), -math.inf(f32));
363 try expectEqual(log2f(-0.0), -math.inf(f32));
364 try expect(math.isPositiveZero(log2f(1.0)));
365 try expectEqual(log2f(2.0), 1.0);
366 try expectEqual(log2f(math.inf(f32)), math.inf(f32));
367 try expect(math.isNan(log2f(-1.0)));
368 try expect(math.isNan(log2f(-math.inf(f32))));
369 try expect(math.isNan(log2f(math.nan(f32))));
370 try expect(math.isNan(log2f(math.snan(f32))));
374 try expectEqual(log2_f32(0.0), -math.inf(f32));
375 try expectEqual(log2_f32(-0.0), -math.inf(f32));
376 try expect(math.isPositiveZero(log2_f32(1.0)));
377 try expectEqual(log2_f32(2.0), 1.0);
378 try expectEqual(log2_f32(math.inf(f32)), math.inf(f32));
379 try expect(math.isNan(log2_f32(-1.0)));
380 try expect(math.isNan(log2_f32(-math.inf(f32))));
381 try expect(math.isNan(log2_f32(math.nan(f32))));
382 try expect(math.isNan(log2_f32(math.snan(f32))));
371383}
372384
373385test "log2f() sanity" {
374 try expect(math.isNan(log2f(-0x1.0223a0p+3)));
375 try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1);
376 try expect(math.isNan(log2f(-0x1.0c34b4p+3)));
377 try expect(math.isNan(log2f(-0x1.a206f0p+2)));
378 try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1);
379 try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
380 try expect(math.isNan(log2f(-0x1.a05cc8p-2)));
381 try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1);
382 try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2);
383 try expect(math.isNan(log2f(-0x1.5b86eap-1)));
386 try expect(math.isNan(log2_f32(-0x1.0223a0p+3)));
387 try expectEqual(log2_f32(0x1.161868p+2), 0x1.0f49acp+1);
388 try expect(math.isNan(log2_f32(-0x1.0c34b4p+3)));
389 try expect(math.isNan(log2_f32(-0x1.a206f0p+2)));
390 try expectEqual(log2_f32(0x1.288bbcp+3), 0x1.9b2676p+1);
391 try expectEqual(log2_f32(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit
392 try expect(math.isNan(log2_f32(-0x1.a05cc8p-2)));
393 try expectEqual(log2_f32(0x1.1f9efap-1), -0x1.a9f89ap-1);
394 try expectEqual(log2_f32(0x1.8c5db0p-1), -0x1.7a2c96p-2);
395 try expect(math.isNan(log2_f32(-0x1.5b86eap-1)));
384396}
385397
386398test "log2f() boundary" {
387 try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value
388 try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value
389 try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value
390 try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0
391 try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
392 try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal
393 try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal
399 try expectEqual(log2_f32(0x1.fffffep+127), 0x1p+7); // Max input value
400 try expectEqual(log2_f32(0x1p-149), -0x1.2ap+7); // Min positive input value
401 try expect(math.isNan(log2_f32(-0x1p-149))); // Min negative input value
402 try expectEqual(log2_f32(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0
403 try expectEqual(log2_f32(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0
404 try expectEqual(log2_f32(0x1p-126), -0x1.f8p+6); // First subnormal
405 try expect(math.isNan(log2_f32(-0x1p-126))); // First negative subnormal
394406
395407}
396408
397409test "log2() special" {
398 try expectEqual(log2(0.0), -math.inf(f64));
399 try expectEqual(log2(-0.0), -math.inf(f64));
400 try expect(math.isPositiveZero(log2(1.0)));
401 try expectEqual(log2(2.0), 1.0);
402 try expectEqual(log2(math.inf(f64)), math.inf(f64));
403 try expect(math.isNan(log2(-1.0)));
404 try expect(math.isNan(log2(-math.inf(f64))));
405 try expect(math.isNan(log2(math.nan(f64))));
406 try expect(math.isNan(log2(math.snan(f64))));
410 try expectEqual(log2_f64(0.0), -math.inf(f64));
411 try expectEqual(log2_f64(-0.0), -math.inf(f64));
412 try expect(math.isPositiveZero(log2_f64(1.0)));
413 try expectEqual(log2_f64(2.0), 1.0);
414 try expectEqual(log2_f64(math.inf(f64)), math.inf(f64));
415 try expect(math.isNan(log2_f64(-1.0)));
416 try expect(math.isNan(log2_f64(-math.inf(f64))));
417 try expect(math.isNan(log2_f64(math.nan(f64))));
418 try expect(math.isNan(log2_f64(math.snan(f64))));
407419}
408420
409421test "log2() sanity" {
410 try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3)));
411 try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
412 try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3)));
413 try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2)));
414 try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
415 try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
416 try expect(math.isNan(log2(-0x1.a05cc754481d1p-2)));
417 try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
418 try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
419 try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1)));
422 try expect(math.isNan(log2_f64(-0x1.02239f3c6a8f1p+3)));
423 try expectEqual(log2_f64(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1);
424 try expect(math.isNan(log2_f64(-0x1.0c34b3e01e6e7p+3)));
425 try expect(math.isNan(log2_f64(-0x1.a206f0a19dcc4p+2)));
426 try expectEqual(log2_f64(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1);
427 try expectEqual(log2_f64(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1);
428 try expect(math.isNan(log2_f64(-0x1.a05cc754481d1p-2)));
429 try expectEqual(log2_f64(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1);
430 try expectEqual(log2_f64(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2);
431 try expect(math.isNan(log2_f64(-0x1.5b86ea8118a0ep-1)));
420432}
421433
422434test "log2() boundary" {
423 try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
424 try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value
425 try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value
426 try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0
427 try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
428 try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal
429 try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal
435 try expectEqual(log2_f64(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value
436 try expectEqual(log2_f64(0x1p-1074), -0x1.0c8p+10); // Min positive input value
437 try expect(math.isNan(log2_f64(-0x1p-1074))); // Min negative input value
438 try expectEqual(log2_f64(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0
439 try expectEqual(log2_f64(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0
440 try expectEqual(log2_f64(0x1p-1022), -0x1.ffp+9); // First subnormal
441 try expect(math.isNan(log2_f64(-0x1p-1022))); // First negative subnormal
430442}
431443
432444test "log2q() special" {
433 try expectEqual(log2q(0.0), -math.inf(f128));
434 try expectEqual(log2q(-0.0), -math.inf(f128));
435 try expect(math.isPositiveZero(log2q(1.0)));
436 try expectEqual(log2q(2.0), 1.0);
437 try expectEqual(log2q(math.inf(f128)), math.inf(f128));
438 try expect(math.isNan(log2q(-1.0)));
439 try expect(math.isNan(log2q(-math.inf(f128))));
440 try expect(math.isNan(log2q(math.nan(f128))));
441 try expect(math.isNan(log2q(math.snan(f128))));
445 try expectEqual(log2_f128(0.0), -math.inf(f128));
446 try expectEqual(log2_f128(-0.0), -math.inf(f128));
447 try expect(math.isPositiveZero(log2_f128(1.0)));
448 try expectEqual(log2_f128(2.0), 1.0);
449 try expectEqual(log2_f128(math.inf(f128)), math.inf(f128));
450 try expect(math.isNan(log2_f128(-1.0)));
451 try expect(math.isNan(log2_f128(-math.inf(f128))));
452 try expect(math.isNan(log2_f128(math.nan(f128))));
453 try expect(math.isNan(log2_f128(math.snan(f128))));
442454}
443455
444456test "log2q() boundary" {
445 try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value
446 try expectEqual(log2q(0x1p-16494), -0x1.01b8p14); // Min positive input value
447 try expect(math.isNan(log2q(-0x1p-16494))); // Min negative input value
448 try expectEqual(log2q(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0
449 try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0
450 try expectEqual(log2q(0x1p-16382), -0x1.fffp13); // First subnormal
451 try expect(math.isNan(log2q(-0x1p-16382))); // First negative subnormal
457 try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value
458 try expectEqual(log2_f128(0x1p-16494), -0x1.01b8p14); // Min positive input value
459 try expect(math.isNan(log2_f128(-0x1p-16494))); // Min negative input value
460 try expectEqual(log2_f128(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0
461 try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0
462 try expectEqual(log2_f128(0x1p-16382), -0x1.fffp13); // First subnormal
463 try expect(math.isNan(log2_f128(-0x1p-16382))); // First negative subnormal
452464}
453465
454466test "log2q() sanity" {
455 try expectEqual(log2q(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1);
456 try expectEqual(log2q(8.346531942223744e15), 5.28900982928636641107356163006646e1);
457 try expectEqual(log2q(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1);
458 try expectEqual(log2q(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1);
459 try expectEqual(log2q(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1);
460 try expectEqual(log2q(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1);
467 try expectEqual(log2_f128(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1);
468 try expectEqual(log2_f128(8.346531942223744e15), 5.28900982928636641107356163006646e1);
469 try expectEqual(log2_f128(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1);
470 try expectEqual(log2_f128(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1);
471 try expectEqual(log2_f128(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1);
472 try expectEqual(log2_f128(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1);
461473 // test near 1
462 try expectEqual(log2q(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2);
463 try expectEqual(log2q(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4);
464 try expectEqual(log2q(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2);
465 try expectEqual(log2q(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2);
466 try expectEqual(log2q(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2);
474 try expectEqual(log2_f128(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2);
475 try expectEqual(log2_f128(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4);
476 try expectEqual(log2_f128(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2);
477 try expectEqual(log2_f128(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2);
478 try expectEqual(log2_f128(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2);
467479}
lib/compiler_rt/mulc3.zig+75-10
......@@ -3,19 +3,80 @@ const isNan = std.math.isNan;
33const isInf = std.math.isInf;
44const copysign = std.math.copysign;
55
6pub fn Complex(comptime T: type) type {
7 return extern struct {
8 real: T,
9 imag: T,
10 };
6const compiler_rt = @import("../compiler_rt.zig");
7const symbol = compiler_rt.symbol;
8const Complex = compiler_rt.Complex;
9
10comptime {
11 if (@import("builtin").zig_backend != .stage2_c) {
12 symbol(&__mulhc3, "__mulhc3");
13 symbol(&__mulsc3, "__mulsc3");
14 symbol(&__muldc3, "__muldc3");
15 symbol(&__mulxc3, "__mulxc3");
16 if (compiler_rt.want_ppc_abi) {
17 symbol(&__multc3, "__mulkc3");
18 } else {
19 symbol(&__multc3, "__multc3");
20 }
21 }
22}
23
24fn __mulhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi {
25 return compiler_rt.f16.complex.toAbi(mul_cf16(
26 compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
27 compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
28 ));
29}
30pub fn mul_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) {
31 return mulc3(f16, a, b);
32}
33
34fn __mulsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi {
35 return compiler_rt.f32.complex.toAbi(mul_cf32(
36 compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
37 compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
38 ));
39}
40pub fn mul_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) {
41 return mulc3(f32, a, b);
42}
43
44fn __muldc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi {
45 return compiler_rt.f64.complex.toAbi(mul_cf64(
46 compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
47 compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
48 ));
49}
50pub fn mul_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) {
51 return mulc3(f64, a, b);
52}
53
54fn __mulxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi {
55 return compiler_rt.f80.complex.toAbi(mul_cf80(
56 compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
57 compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
58 ));
59}
60pub fn mul_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) {
61 return mulc3(f80, a, b);
62}
63
64fn __multc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi {
65 return compiler_rt.f128.complex.toAbi(mul_cf128(
66 compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }),
67 compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }),
68 ));
69}
70pub fn mul_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) {
71 return mulc3(f128, a, b);
1172}
1273
1374/// Implementation based on Annex G of C17 Standard (N2176)
14pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Complex(T) {
15 var a = a_in;
16 var b = b_in;
17 var c = c_in;
18 var d = d_in;
75inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) {
76 var a = lhs.real;
77 var b = lhs.imag;
78 var c = rhs.real;
79 var d = rhs.imag;
1980
2081 const ac = a * c;
2182 const bd = b * d;
......@@ -77,3 +138,7 @@ pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Comple
77138 }
78139 return z;
79140}
141
142test {
143 _ = @import("mulc3_test.zig");
144}
lib/compiler_rt/mulc3_test.zig+23-42
......@@ -2,64 +2,45 @@ const std = @import("std");
22const math = std.math;
33const expect = std.testing.expect;
44
5const Complex = @import("./mulc3.zig").Complex;
6const __mulhc3 = @import("./mulhc3.zig").__mulhc3;
7const __mulsc3 = @import("./mulsc3.zig").__mulsc3;
8const __muldc3 = @import("./muldc3.zig").__muldc3;
9const __mulxc3 = @import("./mulxc3.zig").__mulxc3;
10const __multc3 = @import("./multc3.zig").__multc3;
5const Complex = @import("../compiler_rt.zig").Complex;
6const impl = @import("mulc3.zig");
7const mul_cf16 = impl.mul_cf16;
8const mul_cf32 = impl.mul_cf32;
9const mul_cf64 = impl.mul_cf64;
10const mul_cf80 = impl.mul_cf80;
11const mul_cf128 = impl.mul_cf128;
1112
1213test "mulc3" {
13 try testMul(f16, __mulhc3);
14 try testMul(f32, __mulsc3);
15 try testMul(f64, __muldc3);
16 try testMul(f80, __mulxc3);
17 try testMul(f128, __multc3);
14 try testMul(f16, mul_cf16);
15 try testMul(f32, mul_cf32);
16 try testMul(f64, mul_cf64);
17 try testMul(f80, mul_cf80);
18 try testMul(f128, mul_cf128);
1819}
1920
20fn testMul(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void {
21fn testMul(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void {
2122 {
22 const a: T = 1.0;
23 const b: T = 0.0;
24 const c: T = -1.0;
25 const d: T = 0.0;
26
27 const result = f(a, b, c, d);
23 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 });
2824 try expect(result.real == -1.0);
29 try expect(result.imag == 0.0);
25 try expect(math.isPositiveZero(result.imag));
3026 }
3127 {
32 const a: T = 1.0;
33 const b: T = 0.0;
34 const c: T = -4.0;
35 const d: T = 0.0;
36
37 const result = f(a, b, c, d);
28 const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 });
3829 try expect(result.real == -4.0);
39 try expect(result.imag == 0.0);
30 try expect(math.isPositiveZero(result.imag));
4031 }
4132 {
4233 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,
4334 // then the result of the * operator is an infinity;
44 const a: T = math.inf(T);
45 const b: T = -math.inf(T);
46 const c: T = 1.0;
47 const d: T = 0.0;
48
49 const result = f(a, b, c, d);
50 try expect(result.real == math.inf(T));
51 try expect(result.imag == -math.inf(T));
35 const result = f(.{ .real = math.inf(T), .imag = -math.inf(T) }, .{ .real = 1.0, .imag = 0.0 });
36 try expect(math.isPositiveInf(result.real));
37 try expect(math.isNegativeInf(result.imag));
5238 }
5339 {
5440 // if one operand is an infinity and the other operand is a nonzero finite number or an infinity,
5541 // then the result of the * operator is an infinity;
56 const a: T = math.inf(T);
57 const b: T = -1.0;
58 const c: T = 1.0;
59 const d: T = math.inf(T);
60
61 const result = f(a, b, c, d);
62 try expect(result.real == math.inf(T));
63 try expect(result.imag == math.inf(T));
42 const result = f(.{ .real = math.inf(T), .imag = -1.0 }, .{ .real = 1.0, .imag = math.inf(T) });
43 try expect(math.isPositiveInf(result.real));
44 try expect(math.isPositiveInf(result.imag));
6445 }
6546}
lib/compiler_rt/muldc3.zig deleted-12
......@@ -1,12 +0,0 @@
1const mulc3 = @import("./mulc3.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 if (@import("builtin").zig_backend != .stage2_c) {
6 symbol(&__muldc3, "__muldc3");
7 }
8}
9
10pub fn __muldc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) mulc3.Complex(f64) {
11 return mulc3.mulc3(f64, a, b, c, d);
12}
lib/compiler_rt/muldf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dmul, "__aeabi_dmul");
8 } else {
9 symbol(&__muldf3, "__muldf3");
10 }
11}
12
13pub fn __muldf3(a: f64, b: f64) callconv(.c) f64 {
14 return mulf3(f64, a, b);
15}
16
17fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return mulf3(f64, a, b);
19}
lib/compiler_rt/mulf3.zig+67-1
......@@ -2,10 +2,76 @@ const std = @import("std");
22const math = std.math;
33const builtin = @import("builtin");
44const compiler_rt = @import("../compiler_rt.zig");
5const symbol = compiler_rt.symbol;
6
7comptime {
8 symbol(&__mulhf3, "__mulhf3");
9 if (compiler_rt.want_aeabi) {
10 symbol(&__aeabi_fmul, "__aeabi_fmul");
11 symbol(&__aeabi_dmul, "__aeabi_dmul");
12 } else {
13 symbol(&__mulsf3, "__mulsf3");
14 symbol(&__muldf3, "__muldf3");
15 }
16 symbol(&__mulxf3, "__mulxf3");
17 if (compiler_rt.want_ppc_abi) {
18 symbol(&__multf3, "__mulkf3");
19 } else if (compiler_rt.want_sparc64_abi) {
20 symbol(&_Qp_mul, "_Qp_mul");
21 } else if (compiler_rt.want_sparc32_abi) {
22 symbol(&__multf3, "_Q_mul");
23 } else {
24 symbol(&__multf3, "__multf3");
25 }
26}
27
28fn __mulhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
29 return compiler_rt.f16.toAbi(mul_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)));
30}
31pub fn mul_f16(a: f16, b: f16) f16 {
32 return mulf3(f16, a, b);
33}
34
35fn __mulsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
36 return compiler_rt.f32.toAbi(mul_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)));
37}
38fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
39 return mul_f32(a, b);
40}
41pub fn mul_f32(a: f32, b: f32) f32 {
42 return mulf3(f32, a, b);
43}
44
45fn __muldf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
46 return compiler_rt.f64.toAbi(mul_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)));
47}
48fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
49 return mul_f64(a, b);
50}
51pub fn mul_f64(a: f64, b: f64) f64 {
52 return mulf3(f64, a, b);
53}
54
55fn __mulxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
56 return compiler_rt.f80.toAbi(mul_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)));
57}
58pub fn mul_f80(a: f80, b: f80) f80 {
59 return mulf3(f80, a, b);
60}
61
62fn __multf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
63 return compiler_rt.f128.toAbi(mul_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)));
64}
65fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
66 c.* = mul_f128(a.*, b.*);
67}
68pub fn mul_f128(a: f128, b: f128) f128 {
69 return mulf3(f128, a, b);
70}
571
672/// Ported from:
773/// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc
8pub inline fn mulf3(comptime T: type, a: T, b: T) T {
74inline fn mulf3(comptime T: type, a: T, b: T) T {
975 @setRuntimeSafety(compiler_rt.test_safety);
1076 const typeWidth = @typeInfo(T).float.bits;
1177 const significandBits = math.floatMantissaBits(T);
lib/compiler_rt/mulf3_test.zig+48-46
......@@ -7,10 +7,12 @@ const math = std.math;
77const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64);
88const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64);
99
10const __multf3 = @import("multf3.zig").__multf3;
11const __mulxf3 = @import("mulxf3.zig").__mulxf3;
12const __muldf3 = @import("muldf3.zig").__muldf3;
13const __mulsf3 = @import("mulsf3.zig").__mulsf3;
10const impl = @import("mulf3.zig");
11const mul_f16 = impl.mul_f16;
12const mul_f32 = impl.mul_f32;
13const mul_f64 = impl.mul_f64;
14const mul_f80 = impl.mul_f80;
15const mul_f128 = impl.mul_f128;
1416
1517// return true if equal
1618// use two 64-bit integers instead of one 128-bit integer
......@@ -34,8 +36,8 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
3436 return false;
3537}
3638
37fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
38 const x = __multf3(a, b);
39fn test_mul_f128(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
40 const x = mul_f128(a, b);
3941
4042 if (compareResultLD(x, expected_hi, expected_lo))
4143 return;
......@@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 {
4951}
5052test "multf3" {
5153 // qNaN * any = qNaN
52 try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
54 try test_mul_f128(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
5355
5456 // NaN * any = NaN
5557 const a = makeNaN128(0x800030000000);
56 try test__multf3(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
58 try test_mul_f128(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
5759 // inf * any = inf
58 try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
60 try test_mul_f128(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
5961
6062 // any * any
61 try test__multf3(
63 try test_mul_f128(
6264 @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))),
6365 @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))),
6466 0x400423e7f9e3c9fc,
6567 0xd906c2c2a85777c4,
6668 );
6769
68 try test__multf3(
70 try test_mul_f128(
6971 @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))),
7072 @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))),
7173 0x3fc52a163c6223fc,
7274 0xc94c4bf0430768b4,
7375 );
7476
75 try test__multf3(
77 try test_mul_f128(
7678 0x1.234425696abcad34a35eeffefdcbap+456,
7779 0x451.ed98d76e5d46e5f24323dff21ffp+600,
7880 0x44293a91de5e0e94,
7981 0xe8ed17cc2cdf64ac,
8082 );
8183
82 try test__multf3(
84 try test_mul_f128(
8385 @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))),
8486 @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))),
8587 0x3d4f37c1a3137cae,
8688 0xfc6807048bc2836a,
8789 );
8890
89 try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
91 try test_mul_f128(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
9092
9193 // Denormal operands.
92 try test__multf3(
94 try test_mul_f128(
9395 0x0.0000000000000000000000000001p-16382,
9496 0x1p16383,
9597 0x3f90000000000000,
9698 0x0,
9799 );
98 try test__multf3(
100 try test_mul_f128(
99101 0x1p16383,
100102 0x0.0000000000000000000000000001p-16382,
101103 0x3f90000000000000,
102104 0x0,
103105 );
104106
105 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002);
106 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);
107 try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
107 try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002);
108 try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);
109 try test_mul_f128(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
108110}
109111
110112const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1)));
111113
112fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
113 const x = __mulxf3(a, b);
114fn test_mul_f80(a: f80, b: f80, expected: u80) !void {
115 const x = mul_f80(a, b);
114116 const rep: u80 = @bitCast(x);
115117
116118 if (rep == expected)
......@@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
124126
125127test "mulxf3" {
126128 // NaN * any = NaN
127 try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
128 try test__mulxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
129 try test_mul_f80(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
130 try test_mul_f80(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
129131
130132 // any * NaN = NaN
131 try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));
132 try test__mulxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
133 try test_mul_f80(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));
134 try test_mul_f80(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
133135
134136 // NaN * inf = NaN
135 try test__mulxf3(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80)));
137 try test_mul_f80(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80)));
136138
137139 // inf * NaN = NaN
138 try test__mulxf3(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80)));
140 try test_mul_f80(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80)));
139141
140142 // inf * inf = inf
141 try test__mulxf3(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
143 try test_mul_f80(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
142144
143145 // inf * -inf = -inf
144 try test__mulxf3(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
146 try test_mul_f80(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
145147
146148 // -inf + inf = -inf
147 try test__mulxf3(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
149 try test_mul_f80(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
148150
149151 // inf * any = inf
150 try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80))));
152 try test_mul_f80(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80))));
151153
152154 // any * inf = inf
153 try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
155 try test_mul_f80(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
154156
155157 // any * any
156 try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);
157 try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact
158
159 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact
160 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down
161 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even
162 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up
163 try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact
164
165 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even
166 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up
167 try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal
168 try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal
169 try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal
158 try test_mul_f80(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);
159 try test_mul_f80(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact
160
161 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact
162 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down
163 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even
164 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up
165 try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact
166
167 try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even
168 try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up
169 try test_mul_f80(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal
170 try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal
171 try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal
170172}
lib/compiler_rt/mulhc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulc3 = @import("./mulc3.zig");
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__mulhc3, "__mulhc3");
8 }
9}
10
11pub fn __mulhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) mulc3.Complex(f16) {
12 return mulc3.mulc3(f16, a, b, c, d);
13}
lib/compiler_rt/mulhf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 symbol(&__mulhf3, "__mulhf3");
7}
8
9pub fn __mulhf3(a: f16, b: f16) callconv(.c) f16 {
10 return mulf3(f16, a, b);
11}
lib/compiler_rt/mulsc3.zig deleted-12
......@@ -1,12 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const mulc3 = @import("./mulc3.zig");
3
4comptime {
5 if (@import("builtin").zig_backend != .stage2_c) {
6 symbol(&__mulsc3, "__mulsc3");
7 }
8}
9
10pub fn __mulsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) mulc3.Complex(f32) {
11 return mulc3.mulc3(f32, a, b, c, d);
12}
lib/compiler_rt/mulsf3.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_fmul, "__aeabi_fmul");
8 } else {
9 symbol(&__mulsf3, "__mulsf3");
10 }
11}
12
13pub fn __mulsf3(a: f32, b: f32) callconv(.c) f32 {
14 return mulf3(f32, a, b);
15}
16
17fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return mulf3(f32, a, b);
19}
lib/compiler_rt/multc3.zig deleted-15
......@@ -1,15 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const mulc3 = @import("./mulc3.zig");
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 if (compiler_rt.want_ppc_abi)
8 symbol(&__multc3, "__mulkc3");
9 symbol(&__multc3, "__multc3");
10 }
11}
12
13pub fn __multc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) mulc3.Complex(f128) {
14 return mulc3.mulc3(f128, a, b, c, d);
15}
lib/compiler_rt/multf3.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__multf3, "__mulkf3");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_mul, "_Qp_mul");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__multf3, "_Q_mul");
12 }
13 symbol(&__multf3, "__multf3");
14}
15
16pub fn __multf3(a: f128, b: f128) callconv(.c) f128 {
17 return mulf3(f128, a, b);
18}
19
20fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
21 c.* = mulf3(f128, a.*, b.*);
22}
lib/compiler_rt/mulvsi3.zig+3-2
......@@ -1,7 +1,8 @@
11const testing = @import("std").testing;
22
33const mulv = @import("mulo.zig");
4const symbol = @import("../compiler_rt.zig").symbol;
4const compiler_rt = @import("../compiler_rt.zig");
5const symbol = compiler_rt.symbol;
56
67comptime {
78 symbol(&__mulvsi3, "__mulvsi3");
......@@ -10,7 +11,7 @@ comptime {
1011pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 {
1112 var overflow: c_int = 0;
1213 const sum = mulv.__mulosi4(a, b, &overflow);
13 if (overflow != 0) @panic("compiler-rt: integer overflow");
14 if (overflow != 0) @panic("integer overflow");
1415 return sum;
1516}
1617
lib/compiler_rt/mulxc3.zig deleted-13
......@@ -1,13 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulc3 = @import("./mulc3.zig");
4
5comptime {
6 if (@import("builtin").zig_backend != .stage2_c) {
7 symbol(&__mulxc3, "__mulxc3");
8 }
9}
10
11pub fn __mulxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) mulc3.Complex(f80) {
12 return mulc3.mulc3(f80, a, b, c, d);
13}
lib/compiler_rt/mulxf3.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const mulf3 = @import("./mulf3.zig").mulf3;
4
5comptime {
6 symbol(&__mulxf3, "__mulxf3");
7}
8
9pub fn __mulxf3(a: f80, b: f80) callconv(.c) f80 {
10 return mulf3(f80, a, b);
11}
lib/compiler_rt/negv.zig+1-2
......@@ -33,8 +33,7 @@ inline fn negvXi(comptime ST: type, a: ST) ST {
3333 };
3434 const N: UT = @bitSizeOf(ST);
3535 const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1))));
36 if (a == min)
37 @panic("compiler_rt negv: overflow");
36 if (a == min) @panic("integer overflow");
3837 return -a;
3938}
4039
lib/compiler_rt/os_version_check.zig-1
......@@ -3,7 +3,6 @@ const testing = std.testing;
33const builtin = @import("builtin");
44const compiler_rt = @import("../compiler_rt.zig");
55const symbol = compiler_rt.symbol;
6const panic = @import("../compiler_rt.zig").panic;
76
87const have_availability_version_check = builtin.os.tag.isDarwin() and
98 builtin.os.version_range.semver.min.order(.{ .major = 10, .minor = 15, .patch = 0 }).compare(.gte);
lib/compiler_rt/parity.zig+2-1
......@@ -1,6 +1,7 @@
11//! parity - if number of bits set is even => 0, else => 1
22//! - pariytXi2_generic for big and little endian
3const symbol = @import("../compiler_rt.zig").symbol;
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
45
56comptime {
67 symbol(&__paritysi2, "__paritysi2");
lib/compiler_rt/popcount.zig+2-1
......@@ -6,7 +6,8 @@
66//! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,
77//! subsubsection "Working with the rightmost bits" and "Sideways addition".
88
9const symbol = @import("../compiler_rt.zig").symbol;
9const compiler_rt = @import("../compiler_rt.zig");
10const symbol = compiler_rt.symbol;
1011
1112comptime {
1213 symbol(&__popcountsi2, "__popcountsi2");
lib/compiler_rt/powiXf2.zig+28-11
......@@ -4,16 +4,18 @@
44//! error propagation and this method is optimized for performance, not accuracy.
55
66const compiler_rt = @import("../compiler_rt.zig");
7const symbol = @import("../compiler_rt.zig").symbol;
7const symbol = compiler_rt.symbol;
88
99comptime {
1010 symbol(&__powihf2, "__powihf2");
1111 symbol(&__powisf2, "__powisf2");
1212 symbol(&__powidf2, "__powidf2");
13 if (compiler_rt.want_ppc_abi)
14 symbol(&__powitf2, "__powikf2");
15 symbol(&__powitf2, "__powitf2");
1613 symbol(&__powixf2, "__powixf2");
14 if (compiler_rt.want_ppc_abi) {
15 symbol(&__powitf2, "__powikf2");
16 } else {
17 symbol(&__powitf2, "__powitf2");
18 }
1719}
1820
1921inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {
......@@ -32,26 +34,41 @@ inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {
3234 return if (is_recip) 1 / r else r;
3335}
3436
35pub fn __powihf2(a: f16, b: i32) callconv(.c) f16 {
37fn __powihf2(a: compiler_rt.f16.Abi, b: i32) callconv(.c) compiler_rt.f16.Abi {
38 return compiler_rt.f16.toAbi(powi_f16(compiler_rt.f16.fromAbi(a), b));
39}
40pub fn powi_f16(a: f16, b: i32) f16 {
3641 return powiXf2(f16, a, b);
3742}
3843
39pub fn __powisf2(a: f32, b: i32) callconv(.c) f32 {
44fn __powisf2(a: compiler_rt.f32.Abi, b: i32) callconv(.c) compiler_rt.f32.Abi {
45 return compiler_rt.f32.toAbi(powi_f32(compiler_rt.f32.fromAbi(a), b));
46}
47pub fn powi_f32(a: f32, b: i32) f32 {
4048 return powiXf2(f32, a, b);
4149}
4250
43pub fn __powidf2(a: f64, b: i32) callconv(.c) f64 {
51fn __powidf2(a: compiler_rt.f64.Abi, b: i32) callconv(.c) compiler_rt.f64.Abi {
52 return compiler_rt.f64.toAbi(powi_f64(compiler_rt.f64.fromAbi(a), b));
53}
54pub fn powi_f64(a: f64, b: i32) f64 {
4455 return powiXf2(f64, a, b);
4556}
4657
47pub fn __powitf2(a: f128, b: i32) callconv(.c) f128 {
48 return powiXf2(f128, a, b);
58fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi {
59 return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b));
4960}
50
51pub fn __powixf2(a: f80, b: i32) callconv(.c) f80 {
61pub fn powi_f80(a: f80, b: i32) f80 {
5262 return powiXf2(f80, a, b);
5363}
5464
65fn __powitf2(a: compiler_rt.f128.Abi, b: i32) callconv(.c) compiler_rt.f128.Abi {
66 return compiler_rt.f128.toAbi(powi_f128(compiler_rt.f128.fromAbi(a), b));
67}
68pub fn powi_f128(a: f128, b: i32) f128 {
69 return powiXf2(f128, a, b);
70}
71
5572test {
5673 _ = @import("powiXf2_test.zig");
5774}
lib/compiler_rt/powiXf2_test.zig+531-525
......@@ -2,562 +2,568 @@
22// powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c
33// powihf2 adapted from powisf2 tests
44
5const powiXf2 = @import("powiXf2.zig");
65const std = @import("std");
7const builtin = @import("builtin");
86const testing = std.testing;
97const math = std.math;
108
11fn test__powihf2(a: f16, b: i32, expected: f16) !void {
12 const result = powiXf2.__powihf2(a, b);
9const impl = @import("powiXf2.zig");
10
11const powi_f16 = impl.powi_f16;
12const powi_f32 = impl.powi_f32;
13const powi_f64 = impl.powi_f64;
14const powi_f80 = impl.powi_f80;
15const powi_f128 = impl.powi_f128;
16
17fn test_powi_f16(a: f16, b: i32, expected: f16) !void {
18 const result = powi_f16(a, b);
1319 try testing.expectEqual(expected, result);
1420}
1521
16fn test__powisf2(a: f32, b: i32, expected: f32) !void {
17 const result = powiXf2.__powisf2(a, b);
22fn test_powi_f32(a: f32, b: i32, expected: f32) !void {
23 const result = powi_f32(a, b);
1824 try testing.expectEqual(expected, result);
1925}
2026
21fn test__powidf2(a: f64, b: i32, expected: f64) !void {
22 const result = powiXf2.__powidf2(a, b);
27fn test_powi_f64(a: f64, b: i32, expected: f64) !void {
28 const result = powi_f64(a, b);
2329 try testing.expectEqual(expected, result);
2430}
2531
26fn test__powitf2(a: f128, b: i32, expected: f128) !void {
27 const result = powiXf2.__powitf2(a, b);
32fn test_powi_f80(a: f80, b: i32, expected: f80) !void {
33 const result = powi_f80(a, b);
2834 try testing.expectEqual(expected, result);
2935}
3036
31fn test__powixf2(a: f80, b: i32, expected: f80) !void {
32 const result = powiXf2.__powixf2(a, b);
37fn test_powi_f128(a: f128, b: i32, expected: f128) !void {
38 const result = powi_f128(a, b);
3339 try testing.expectEqual(expected, result);
3440}
3541
36test "powihf2" {
42test powi_f16 {
3743 const inf_f16 = math.inf(f16);
38 try test__powisf2(0, 0, 1);
39 try test__powihf2(1, 0, 1);
40 try test__powihf2(1.5, 0, 1);
41 try test__powihf2(2, 0, 1);
42 try test__powihf2(inf_f16, 0, 1);
43
44 try test__powihf2(-0.0, 0, 1);
45 try test__powihf2(-1, 0, 1);
46 try test__powihf2(-1.5, 0, 1);
47 try test__powihf2(-2, 0, 1);
48 try test__powihf2(-inf_f16, 0, 1);
49
50 try test__powihf2(0, 1, 0);
51 try test__powihf2(0, 2, 0);
52 try test__powihf2(0, 3, 0);
53 try test__powihf2(0, 4, 0);
54 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
55 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
56
57 try test__powihf2(-0.0, 1, -0.0);
58 try test__powihf2(-0.0, 2, 0);
59 try test__powihf2(-0.0, 3, -0.0);
60 try test__powihf2(-0.0, 4, 0);
61 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
62 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
63
64 try test__powihf2(1, 1, 1);
65 try test__powihf2(1, 2, 1);
66 try test__powihf2(1, 3, 1);
67 try test__powihf2(1, 4, 1);
68 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
69 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
70
71 try test__powihf2(inf_f16, 1, inf_f16);
72 try test__powihf2(inf_f16, 2, inf_f16);
73 try test__powihf2(inf_f16, 3, inf_f16);
74 try test__powihf2(inf_f16, 4, inf_f16);
75 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
76 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);
77
78 try test__powihf2(-inf_f16, 1, -inf_f16);
79 try test__powihf2(-inf_f16, 2, inf_f16);
80 try test__powihf2(-inf_f16, 3, -inf_f16);
81 try test__powihf2(-inf_f16, 4, inf_f16);
82 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
83 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);
44 try test_powi_f16(0, 0, 1);
45 try test_powi_f16(1, 0, 1);
46 try test_powi_f16(1.5, 0, 1);
47 try test_powi_f16(2, 0, 1);
48 try test_powi_f16(inf_f16, 0, 1);
49
50 try test_powi_f16(-0.0, 0, 1);
51 try test_powi_f16(-1, 0, 1);
52 try test_powi_f16(-1.5, 0, 1);
53 try test_powi_f16(-2, 0, 1);
54 try test_powi_f16(-inf_f16, 0, 1);
55
56 try test_powi_f16(0, 1, 0);
57 try test_powi_f16(0, 2, 0);
58 try test_powi_f16(0, 3, 0);
59 try test_powi_f16(0, 4, 0);
60 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
61 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
62
63 try test_powi_f16(-0.0, 1, -0.0);
64 try test_powi_f16(-0.0, 2, 0);
65 try test_powi_f16(-0.0, 3, -0.0);
66 try test_powi_f16(-0.0, 4, 0);
67 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
68 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
69
70 try test_powi_f16(1, 1, 1);
71 try test_powi_f16(1, 2, 1);
72 try test_powi_f16(1, 3, 1);
73 try test_powi_f16(1, 4, 1);
74 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
75 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
76
77 try test_powi_f16(inf_f16, 1, inf_f16);
78 try test_powi_f16(inf_f16, 2, inf_f16);
79 try test_powi_f16(inf_f16, 3, inf_f16);
80 try test_powi_f16(inf_f16, 4, inf_f16);
81 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
82 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);
83
84 try test_powi_f16(-inf_f16, 1, -inf_f16);
85 try test_powi_f16(-inf_f16, 2, inf_f16);
86 try test_powi_f16(-inf_f16, 3, -inf_f16);
87 try test_powi_f16(-inf_f16, 4, inf_f16);
88 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
89 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);
8490 //
85 try test__powihf2(0, -1, inf_f16);
86 try test__powihf2(0, -2, inf_f16);
87 try test__powihf2(0, -3, inf_f16);
88 try test__powihf2(0, -4, inf_f16);
89 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf
90 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16);
91 try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
92
93 try test__powihf2(-0.0, -1, -inf_f16);
94 try test__powihf2(-0.0, -2, inf_f16);
95 try test__powihf2(-0.0, -3, -inf_f16);
96 try test__powihf2(-0.0, -4, inf_f16);
97 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf
98 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf
99 try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
100
101 try test__powihf2(1, -1, 1);
102 try test__powihf2(1, -2, 1);
103 try test__powihf2(1, -3, 1);
104 try test__powihf2(1, -4, 1);
105 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1
106 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
107 try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
108
109 try test__powihf2(inf_f16, -1, 0);
110 try test__powihf2(inf_f16, -2, 0);
111 try test__powihf2(inf_f16, -3, 0);
112 try test__powihf2(inf_f16, -4, 0);
113 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
114 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
115 try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
91 try test_powi_f16(0, -1, inf_f16);
92 try test_powi_f16(0, -2, inf_f16);
93 try test_powi_f16(0, -3, inf_f16);
94 try test_powi_f16(0, -4, inf_f16);
95 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf
96 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16);
97 try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
98
99 try test_powi_f16(-0.0, -1, -inf_f16);
100 try test_powi_f16(-0.0, -2, inf_f16);
101 try test_powi_f16(-0.0, -3, -inf_f16);
102 try test_powi_f16(-0.0, -4, inf_f16);
103 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf
104 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf
105 try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
106
107 try test_powi_f16(1, -1, 1);
108 try test_powi_f16(1, -2, 1);
109 try test_powi_f16(1, -3, 1);
110 try test_powi_f16(1, -4, 1);
111 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1
112 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
113 try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
114
115 try test_powi_f16(inf_f16, -1, 0);
116 try test_powi_f16(inf_f16, -2, 0);
117 try test_powi_f16(inf_f16, -3, 0);
118 try test_powi_f16(inf_f16, -4, 0);
119 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
120 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
121 try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
116122 //
117 try test__powihf2(-inf_f16, -1, -0.0);
118 try test__powihf2(-inf_f16, -2, 0);
119 try test__powihf2(-inf_f16, -3, -0.0);
120 try test__powihf2(-inf_f16, -4, 0);
121 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
122 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
123 try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
124
125 try test__powihf2(2, 10, 1024.0);
126 try test__powihf2(-2, 10, 1024.0);
127 try test__powihf2(2, -10, 1.0 / 1024.0);
128 try test__powihf2(-2, -10, 1.0 / 1024.0);
129
130 try test__powihf2(2, 14, 16384.0);
131 try test__powihf2(-2, 14, 16384.0);
132 try test__powihf2(2, 15, 32768.0);
133 try test__powihf2(-2, 15, -32768.0);
134 try test__powihf2(2, 16, inf_f16);
135 try test__powihf2(-2, 16, inf_f16);
136
137 try test__powihf2(2, -13, 1.0 / 8192.0);
138 try test__powihf2(-2, -13, -1.0 / 8192.0);
139 try test__powihf2(2, -15, 1.0 / 32768.0);
140 try test__powihf2(-2, -15, -1.0 / 32768.0);
141 try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)
142 try test__powihf2(-2, -16, 0.0); // expected = 0.0 = 1/(2**16)
123 try test_powi_f16(-inf_f16, -1, -0.0);
124 try test_powi_f16(-inf_f16, -2, 0);
125 try test_powi_f16(-inf_f16, -3, -0.0);
126 try test_powi_f16(-inf_f16, -4, 0);
127 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
128 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
129 try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
130
131 try test_powi_f16(2, 10, 1024.0);
132 try test_powi_f16(-2, 10, 1024.0);
133 try test_powi_f16(2, -10, 1.0 / 1024.0);
134 try test_powi_f16(-2, -10, 1.0 / 1024.0);
135
136 try test_powi_f16(2, 14, 16384.0);
137 try test_powi_f16(-2, 14, 16384.0);
138 try test_powi_f16(2, 15, 32768.0);
139 try test_powi_f16(-2, 15, -32768.0);
140 try test_powi_f16(2, 16, inf_f16);
141 try test_powi_f16(-2, 16, inf_f16);
142
143 try test_powi_f16(2, -13, 1.0 / 8192.0);
144 try test_powi_f16(-2, -13, -1.0 / 8192.0);
145 try test_powi_f16(2, -15, 1.0 / 32768.0);
146 try test_powi_f16(-2, -15, -1.0 / 32768.0);
147 try test_powi_f16(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)
148 try test_powi_f16(-2, -16, 0.0); // expected = 0.0 = 1/(2**16)
143149}
144150
145test "powisf2" {
151test powi_f32 {
146152 const inf_f32 = math.inf(f32);
147 try test__powisf2(0, 0, 1);
148 try test__powisf2(1, 0, 1);
149 try test__powisf2(1.5, 0, 1);
150 try test__powisf2(2, 0, 1);
151 try test__powisf2(inf_f32, 0, 1);
152
153 try test__powisf2(-0.0, 0, 1);
154 try test__powisf2(-1, 0, 1);
155 try test__powisf2(-1.5, 0, 1);
156 try test__powisf2(-2, 0, 1);
157 try test__powisf2(-inf_f32, 0, 1);
158
159 try test__powisf2(0, 1, 0);
160 try test__powisf2(0, 2, 0);
161 try test__powisf2(0, 3, 0);
162 try test__powisf2(0, 4, 0);
163 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
164 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
165
166 try test__powisf2(-0.0, 1, -0.0);
167 try test__powisf2(-0.0, 2, 0);
168 try test__powisf2(-0.0, 3, -0.0);
169 try test__powisf2(-0.0, 4, 0);
170 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
171 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
172
173 try test__powisf2(1, 1, 1);
174 try test__powisf2(1, 2, 1);
175 try test__powisf2(1, 3, 1);
176 try test__powisf2(1, 4, 1);
177 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
178 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
179
180 try test__powisf2(inf_f32, 1, inf_f32);
181 try test__powisf2(inf_f32, 2, inf_f32);
182 try test__powisf2(inf_f32, 3, inf_f32);
183 try test__powisf2(inf_f32, 4, inf_f32);
184 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
185 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);
186
187 try test__powisf2(-inf_f32, 1, -inf_f32);
188 try test__powisf2(-inf_f32, 2, inf_f32);
189 try test__powisf2(-inf_f32, 3, -inf_f32);
190 try test__powisf2(-inf_f32, 4, inf_f32);
191 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
192 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);
193
194 try test__powisf2(0, -1, inf_f32);
195 try test__powisf2(0, -2, inf_f32);
196 try test__powisf2(0, -3, inf_f32);
197 try test__powisf2(0, -4, inf_f32);
198 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
199 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);
200 try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
201
202 try test__powisf2(-0.0, -1, -inf_f32);
203 try test__powisf2(-0.0, -2, inf_f32);
204 try test__powisf2(-0.0, -3, -inf_f32);
205 try test__powisf2(-0.0, -4, inf_f32);
206 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
207 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);
208 try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
209
210 try test__powisf2(1, -1, 1);
211 try test__powisf2(1, -2, 1);
212 try test__powisf2(1, -3, 1);
213 try test__powisf2(1, -4, 1);
214 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
215 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
216 try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
217
218 try test__powisf2(inf_f32, -1, 0);
219 try test__powisf2(inf_f32, -2, 0);
220 try test__powisf2(inf_f32, -3, 0);
221 try test__powisf2(inf_f32, -4, 0);
222 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
223 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
224 try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
225
226 try test__powisf2(-inf_f32, -1, -0.0);
227 try test__powisf2(-inf_f32, -2, 0);
228 try test__powisf2(-inf_f32, -3, -0.0);
229 try test__powisf2(-inf_f32, -4, 0);
230 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
231 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
232 try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
233
234 try test__powisf2(2.0, 10, 1024.0);
235 try test__powisf2(-2, 10, 1024.0);
236 try test__powisf2(2, -10, 1.0 / 1024.0);
237 try test__powisf2(-2, -10, 1.0 / 1024.0);
153 try test_powi_f32(0, 0, 1);
154 try test_powi_f32(1, 0, 1);
155 try test_powi_f32(1.5, 0, 1);
156 try test_powi_f32(2, 0, 1);
157 try test_powi_f32(inf_f32, 0, 1);
158
159 try test_powi_f32(-0.0, 0, 1);
160 try test_powi_f32(-1, 0, 1);
161 try test_powi_f32(-1.5, 0, 1);
162 try test_powi_f32(-2, 0, 1);
163 try test_powi_f32(-inf_f32, 0, 1);
164
165 try test_powi_f32(0, 1, 0);
166 try test_powi_f32(0, 2, 0);
167 try test_powi_f32(0, 3, 0);
168 try test_powi_f32(0, 4, 0);
169 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
170 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
171
172 try test_powi_f32(-0.0, 1, -0.0);
173 try test_powi_f32(-0.0, 2, 0);
174 try test_powi_f32(-0.0, 3, -0.0);
175 try test_powi_f32(-0.0, 4, 0);
176 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
177 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
178
179 try test_powi_f32(1, 1, 1);
180 try test_powi_f32(1, 2, 1);
181 try test_powi_f32(1, 3, 1);
182 try test_powi_f32(1, 4, 1);
183 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
184 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
185
186 try test_powi_f32(inf_f32, 1, inf_f32);
187 try test_powi_f32(inf_f32, 2, inf_f32);
188 try test_powi_f32(inf_f32, 3, inf_f32);
189 try test_powi_f32(inf_f32, 4, inf_f32);
190 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
191 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);
192
193 try test_powi_f32(-inf_f32, 1, -inf_f32);
194 try test_powi_f32(-inf_f32, 2, inf_f32);
195 try test_powi_f32(-inf_f32, 3, -inf_f32);
196 try test_powi_f32(-inf_f32, 4, inf_f32);
197 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
198 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);
199
200 try test_powi_f32(0, -1, inf_f32);
201 try test_powi_f32(0, -2, inf_f32);
202 try test_powi_f32(0, -3, inf_f32);
203 try test_powi_f32(0, -4, inf_f32);
204 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
205 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);
206 try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
207
208 try test_powi_f32(-0.0, -1, -inf_f32);
209 try test_powi_f32(-0.0, -2, inf_f32);
210 try test_powi_f32(-0.0, -3, -inf_f32);
211 try test_powi_f32(-0.0, -4, inf_f32);
212 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
213 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);
214 try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
215
216 try test_powi_f32(1, -1, 1);
217 try test_powi_f32(1, -2, 1);
218 try test_powi_f32(1, -3, 1);
219 try test_powi_f32(1, -4, 1);
220 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
221 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
222 try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
223
224 try test_powi_f32(inf_f32, -1, 0);
225 try test_powi_f32(inf_f32, -2, 0);
226 try test_powi_f32(inf_f32, -3, 0);
227 try test_powi_f32(inf_f32, -4, 0);
228 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
229 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
230 try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
231
232 try test_powi_f32(-inf_f32, -1, -0.0);
233 try test_powi_f32(-inf_f32, -2, 0);
234 try test_powi_f32(-inf_f32, -3, -0.0);
235 try test_powi_f32(-inf_f32, -4, 0);
236 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
237 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
238 try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
239
240 try test_powi_f32(2.0, 10, 1024.0);
241 try test_powi_f32(-2, 10, 1024.0);
242 try test_powi_f32(2, -10, 1.0 / 1024.0);
243 try test_powi_f32(-2, -10, 1.0 / 1024.0);
238244 //
239 try test__powisf2(2, 19, 524288.0);
240 try test__powisf2(-2, 19, -524288.0);
241 try test__powisf2(2, -19, 1.0 / 524288.0);
242 try test__powisf2(-2, -19, -1.0 / 524288.0);
243
244 try test__powisf2(2, 31, 2147483648.0);
245 try test__powisf2(-2, 31, -2147483648.0);
246 try test__powisf2(2, -31, 1.0 / 2147483648.0);
247 try test__powisf2(-2, -31, -1.0 / 2147483648.0);
245 try test_powi_f32(2, 19, 524288.0);
246 try test_powi_f32(-2, 19, -524288.0);
247 try test_powi_f32(2, -19, 1.0 / 524288.0);
248 try test_powi_f32(-2, -19, -1.0 / 524288.0);
249
250 try test_powi_f32(2, 31, 2147483648.0);
251 try test_powi_f32(-2, 31, -2147483648.0);
252 try test_powi_f32(2, -31, 1.0 / 2147483648.0);
253 try test_powi_f32(-2, -31, -1.0 / 2147483648.0);
248254}
249255
250test "powidf2" {
256test powi_f64 {
251257 const inf_f64 = math.inf(f64);
252 try test__powidf2(0, 0, 1);
253 try test__powidf2(1, 0, 1);
254 try test__powidf2(1.5, 0, 1);
255 try test__powidf2(2, 0, 1);
256 try test__powidf2(inf_f64, 0, 1);
257
258 try test__powidf2(-0.0, 0, 1);
259 try test__powidf2(-1, 0, 1);
260 try test__powidf2(-1.5, 0, 1);
261 try test__powidf2(-2, 0, 1);
262 try test__powidf2(-inf_f64, 0, 1);
263
264 try test__powidf2(0, 1, 0);
265 try test__powidf2(0, 2, 0);
266 try test__powidf2(0, 3, 0);
267 try test__powidf2(0, 4, 0);
268 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
269 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
270
271 try test__powidf2(-0.0, 1, -0.0);
272 try test__powidf2(-0.0, 2, 0);
273 try test__powidf2(-0.0, 3, -0.0);
274 try test__powidf2(-0.0, 4, 0);
275 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
276 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
277
278 try test__powidf2(1, 1, 1);
279 try test__powidf2(1, 2, 1);
280 try test__powidf2(1, 3, 1);
281 try test__powidf2(1, 4, 1);
282 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
283 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
284
285 try test__powidf2(inf_f64, 1, inf_f64);
286 try test__powidf2(inf_f64, 2, inf_f64);
287 try test__powidf2(inf_f64, 3, inf_f64);
288 try test__powidf2(inf_f64, 4, inf_f64);
289 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
290 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);
291
292 try test__powidf2(-inf_f64, 1, -inf_f64);
293 try test__powidf2(-inf_f64, 2, inf_f64);
294 try test__powidf2(-inf_f64, 3, -inf_f64);
295 try test__powidf2(-inf_f64, 4, inf_f64);
296 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
297 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);
298
299 try test__powidf2(0, -1, inf_f64);
300 try test__powidf2(0, -2, inf_f64);
301 try test__powidf2(0, -3, inf_f64);
302 try test__powidf2(0, -4, inf_f64);
303 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
304 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);
305 try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
306
307 try test__powidf2(-0.0, -1, -inf_f64);
308 try test__powidf2(-0.0, -2, inf_f64);
309 try test__powidf2(-0.0, -3, -inf_f64);
310 try test__powidf2(-0.0, -4, inf_f64);
311 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
312 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);
313 try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
314
315 try test__powidf2(1, -1, 1);
316 try test__powidf2(1, -2, 1);
317 try test__powidf2(1, -3, 1);
318 try test__powidf2(1, -4, 1);
319 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
320 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
321 try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
322
323 try test__powidf2(inf_f64, -1, 0);
324 try test__powidf2(inf_f64, -2, 0);
325 try test__powidf2(inf_f64, -3, 0);
326 try test__powidf2(inf_f64, -4, 0);
327 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
328 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
329 try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
330
331 try test__powidf2(-inf_f64, -1, -0.0);
332 try test__powidf2(-inf_f64, -2, 0);
333 try test__powidf2(-inf_f64, -3, -0.0);
334 try test__powidf2(-inf_f64, -4, 0);
335 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
336 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
337 try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
338
339 try test__powidf2(2, 10, 1024.0);
340 try test__powidf2(-2, 10, 1024.0);
341 try test__powidf2(2, -10, 1.0 / 1024.0);
342 try test__powidf2(-2, -10, 1.0 / 1024.0);
343
344 try test__powidf2(2, 19, 524288.0);
345 try test__powidf2(-2, 19, -524288.0);
346 try test__powidf2(2, -19, 1.0 / 524288.0);
347 try test__powidf2(-2, -19, -1.0 / 524288.0);
348
349 try test__powidf2(2, 31, 2147483648.0);
350 try test__powidf2(-2, 31, -2147483648.0);
351 try test__powidf2(2, -31, 1.0 / 2147483648.0);
352 try test__powidf2(-2, -31, -1.0 / 2147483648.0);
258 try test_powi_f64(0, 0, 1);
259 try test_powi_f64(1, 0, 1);
260 try test_powi_f64(1.5, 0, 1);
261 try test_powi_f64(2, 0, 1);
262 try test_powi_f64(inf_f64, 0, 1);
263
264 try test_powi_f64(-0.0, 0, 1);
265 try test_powi_f64(-1, 0, 1);
266 try test_powi_f64(-1.5, 0, 1);
267 try test_powi_f64(-2, 0, 1);
268 try test_powi_f64(-inf_f64, 0, 1);
269
270 try test_powi_f64(0, 1, 0);
271 try test_powi_f64(0, 2, 0);
272 try test_powi_f64(0, 3, 0);
273 try test_powi_f64(0, 4, 0);
274 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
275 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
276
277 try test_powi_f64(-0.0, 1, -0.0);
278 try test_powi_f64(-0.0, 2, 0);
279 try test_powi_f64(-0.0, 3, -0.0);
280 try test_powi_f64(-0.0, 4, 0);
281 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
282 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
283
284 try test_powi_f64(1, 1, 1);
285 try test_powi_f64(1, 2, 1);
286 try test_powi_f64(1, 3, 1);
287 try test_powi_f64(1, 4, 1);
288 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
289 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
290
291 try test_powi_f64(inf_f64, 1, inf_f64);
292 try test_powi_f64(inf_f64, 2, inf_f64);
293 try test_powi_f64(inf_f64, 3, inf_f64);
294 try test_powi_f64(inf_f64, 4, inf_f64);
295 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
296 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);
297
298 try test_powi_f64(-inf_f64, 1, -inf_f64);
299 try test_powi_f64(-inf_f64, 2, inf_f64);
300 try test_powi_f64(-inf_f64, 3, -inf_f64);
301 try test_powi_f64(-inf_f64, 4, inf_f64);
302 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
303 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);
304
305 try test_powi_f64(0, -1, inf_f64);
306 try test_powi_f64(0, -2, inf_f64);
307 try test_powi_f64(0, -3, inf_f64);
308 try test_powi_f64(0, -4, inf_f64);
309 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
310 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);
311 try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
312
313 try test_powi_f64(-0.0, -1, -inf_f64);
314 try test_powi_f64(-0.0, -2, inf_f64);
315 try test_powi_f64(-0.0, -3, -inf_f64);
316 try test_powi_f64(-0.0, -4, inf_f64);
317 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
318 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);
319 try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
320
321 try test_powi_f64(1, -1, 1);
322 try test_powi_f64(1, -2, 1);
323 try test_powi_f64(1, -3, 1);
324 try test_powi_f64(1, -4, 1);
325 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
326 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
327 try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
328
329 try test_powi_f64(inf_f64, -1, 0);
330 try test_powi_f64(inf_f64, -2, 0);
331 try test_powi_f64(inf_f64, -3, 0);
332 try test_powi_f64(inf_f64, -4, 0);
333 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
334 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
335 try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
336
337 try test_powi_f64(-inf_f64, -1, -0.0);
338 try test_powi_f64(-inf_f64, -2, 0);
339 try test_powi_f64(-inf_f64, -3, -0.0);
340 try test_powi_f64(-inf_f64, -4, 0);
341 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
342 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
343 try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
344
345 try test_powi_f64(2, 10, 1024.0);
346 try test_powi_f64(-2, 10, 1024.0);
347 try test_powi_f64(2, -10, 1.0 / 1024.0);
348 try test_powi_f64(-2, -10, 1.0 / 1024.0);
349
350 try test_powi_f64(2, 19, 524288.0);
351 try test_powi_f64(-2, 19, -524288.0);
352 try test_powi_f64(2, -19, 1.0 / 524288.0);
353 try test_powi_f64(-2, -19, -1.0 / 524288.0);
354
355 try test_powi_f64(2, 31, 2147483648.0);
356 try test_powi_f64(-2, 31, -2147483648.0);
357 try test_powi_f64(2, -31, 1.0 / 2147483648.0);
358 try test_powi_f64(-2, -31, -1.0 / 2147483648.0);
353359}
354360
355test "powitf2" {
356 const inf_f128 = math.inf(f128);
357 try test__powitf2(0, 0, 1);
358 try test__powitf2(1, 0, 1);
359 try test__powitf2(1.5, 0, 1);
360 try test__powitf2(2, 0, 1);
361 try test__powitf2(inf_f128, 0, 1);
362
363 try test__powitf2(-0.0, 0, 1);
364 try test__powitf2(-1, 0, 1);
365 try test__powitf2(-1.5, 0, 1);
366 try test__powitf2(-2, 0, 1);
367 try test__powitf2(-inf_f128, 0, 1);
368
369 try test__powitf2(0, 1, 0);
370 try test__powitf2(0, 2, 0);
371 try test__powitf2(0, 3, 0);
372 try test__powitf2(0, 4, 0);
373 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
374 try test__powitf2(0, 0x7FFFFFFF, 0);
375
376 try test__powitf2(-0.0, 1, -0.0);
377 try test__powitf2(-0.0, 2, 0);
378 try test__powitf2(-0.0, 3, -0.0);
379 try test__powitf2(-0.0, 4, 0);
380 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
381 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
382
383 try test__powitf2(1, 1, 1);
384 try test__powitf2(1, 2, 1);
385 try test__powitf2(1, 3, 1);
386 try test__powitf2(1, 4, 1);
387 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
388 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
389
390 try test__powitf2(inf_f128, 1, inf_f128);
391 try test__powitf2(inf_f128, 2, inf_f128);
392 try test__powitf2(inf_f128, 3, inf_f128);
393 try test__powitf2(inf_f128, 4, inf_f128);
394 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
395 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);
396
397 try test__powitf2(-inf_f128, 1, -inf_f128);
398 try test__powitf2(-inf_f128, 2, inf_f128);
399 try test__powitf2(-inf_f128, 3, -inf_f128);
400 try test__powitf2(-inf_f128, 4, inf_f128);
401 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
402 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);
403
404 try test__powitf2(0, -1, inf_f128);
405 try test__powitf2(0, -2, inf_f128);
406 try test__powitf2(0, -3, inf_f128);
407 try test__powitf2(0, -4, inf_f128);
408 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
409 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);
410 try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
411
412 try test__powitf2(-0.0, -1, -inf_f128);
413 try test__powitf2(-0.0, -2, inf_f128);
414 try test__powitf2(-0.0, -3, -inf_f128);
415 try test__powitf2(-0.0, -4, inf_f128);
416 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
417 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);
418 try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
419
420 try test__powitf2(1, -1, 1);
421 try test__powitf2(1, -2, 1);
422 try test__powitf2(1, -3, 1);
423 try test__powitf2(1, -4, 1);
424 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
425 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
426 try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
427
428 try test__powitf2(inf_f128, -1, 0);
429 try test__powitf2(inf_f128, -2, 0);
430 try test__powitf2(inf_f128, -3, 0);
431 try test__powitf2(inf_f128, -4, 0);
432 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
433 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
434 try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
435
436 try test__powitf2(-inf_f128, -1, -0.0);
437 try test__powitf2(-inf_f128, -2, 0);
438 try test__powitf2(-inf_f128, -3, -0.0);
439 try test__powitf2(-inf_f128, -4, 0);
440 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
441 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
442 try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
443
444 try test__powitf2(2, 10, 1024.0);
445 try test__powitf2(-2, 10, 1024.0);
446 try test__powitf2(2, -10, 1.0 / 1024.0);
447 try test__powitf2(-2, -10, 1.0 / 1024.0);
448
449 try test__powitf2(2, 19, 524288.0);
450 try test__powitf2(-2, 19, -524288.0);
451 try test__powitf2(2, -19, 1.0 / 524288.0);
452 try test__powitf2(-2, -19, -1.0 / 524288.0);
453
454 try test__powitf2(2, 31, 2147483648.0);
455 try test__powitf2(-2, 31, -2147483648.0);
456 try test__powitf2(2, -31, 1.0 / 2147483648.0);
457 try test__powitf2(-2, -31, -1.0 / 2147483648.0);
361test powi_f80 {
362 const inf_f80 = math.inf(f80);
363 try test_powi_f80(0, 0, 1);
364 try test_powi_f80(1, 0, 1);
365 try test_powi_f80(1.5, 0, 1);
366 try test_powi_f80(2, 0, 1);
367 try test_powi_f80(inf_f80, 0, 1);
368
369 try test_powi_f80(-0.0, 0, 1);
370 try test_powi_f80(-1, 0, 1);
371 try test_powi_f80(-1.5, 0, 1);
372 try test_powi_f80(-2, 0, 1);
373 try test_powi_f80(-inf_f80, 0, 1);
374
375 try test_powi_f80(0, 1, 0);
376 try test_powi_f80(0, 2, 0);
377 try test_powi_f80(0, 3, 0);
378 try test_powi_f80(0, 4, 0);
379 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
380 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
381
382 try test_powi_f80(-0.0, 1, -0.0);
383 try test_powi_f80(-0.0, 2, 0);
384 try test_powi_f80(-0.0, 3, -0.0);
385 try test_powi_f80(-0.0, 4, 0);
386 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
387 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
388
389 try test_powi_f80(1, 1, 1);
390 try test_powi_f80(1, 2, 1);
391 try test_powi_f80(1, 3, 1);
392 try test_powi_f80(1, 4, 1);
393 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
394 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
395
396 try test_powi_f80(inf_f80, 1, inf_f80);
397 try test_powi_f80(inf_f80, 2, inf_f80);
398 try test_powi_f80(inf_f80, 3, inf_f80);
399 try test_powi_f80(inf_f80, 4, inf_f80);
400 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
401 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);
402
403 try test_powi_f80(-inf_f80, 1, -inf_f80);
404 try test_powi_f80(-inf_f80, 2, inf_f80);
405 try test_powi_f80(-inf_f80, 3, -inf_f80);
406 try test_powi_f80(-inf_f80, 4, inf_f80);
407 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
408 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);
409
410 try test_powi_f80(0, -1, inf_f80);
411 try test_powi_f80(0, -2, inf_f80);
412 try test_powi_f80(0, -3, inf_f80);
413 try test_powi_f80(0, -4, inf_f80);
414 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
415 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);
416 try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
417
418 try test_powi_f80(-0.0, -1, -inf_f80);
419 try test_powi_f80(-0.0, -2, inf_f80);
420 try test_powi_f80(-0.0, -3, -inf_f80);
421 try test_powi_f80(-0.0, -4, inf_f80);
422 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
423 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);
424 try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
425
426 try test_powi_f80(1, -1, 1);
427 try test_powi_f80(1, -2, 1);
428 try test_powi_f80(1, -3, 1);
429 try test_powi_f80(1, -4, 1);
430 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
431 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
432 try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
433
434 try test_powi_f80(inf_f80, -1, 0);
435 try test_powi_f80(inf_f80, -2, 0);
436 try test_powi_f80(inf_f80, -3, 0);
437 try test_powi_f80(inf_f80, -4, 0);
438 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
439 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
440 try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
441
442 try test_powi_f80(-inf_f80, -1, -0.0);
443 try test_powi_f80(-inf_f80, -2, 0);
444 try test_powi_f80(-inf_f80, -3, -0.0);
445 try test_powi_f80(-inf_f80, -4, 0);
446 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
447 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
448 try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
449
450 try test_powi_f80(2, 10, 1024.0);
451 try test_powi_f80(-2, 10, 1024.0);
452 try test_powi_f80(2, -10, 1.0 / 1024.0);
453 try test_powi_f80(-2, -10, 1.0 / 1024.0);
454
455 try test_powi_f80(2, 19, 524288.0);
456 try test_powi_f80(-2, 19, -524288.0);
457 try test_powi_f80(2, -19, 1.0 / 524288.0);
458 try test_powi_f80(-2, -19, -1.0 / 524288.0);
459
460 try test_powi_f80(2, 31, 2147483648.0);
461 try test_powi_f80(-2, 31, -2147483648.0);
462 try test_powi_f80(2, -31, 1.0 / 2147483648.0);
463 try test_powi_f80(-2, -31, -1.0 / 2147483648.0);
458464}
459465
460test "powixf2" {
461 const inf_f80 = math.inf(f80);
462 try test__powixf2(0, 0, 1);
463 try test__powixf2(1, 0, 1);
464 try test__powixf2(1.5, 0, 1);
465 try test__powixf2(2, 0, 1);
466 try test__powixf2(inf_f80, 0, 1);
467
468 try test__powixf2(-0.0, 0, 1);
469 try test__powixf2(-1, 0, 1);
470 try test__powixf2(-1.5, 0, 1);
471 try test__powixf2(-2, 0, 1);
472 try test__powixf2(-inf_f80, 0, 1);
473
474 try test__powixf2(0, 1, 0);
475 try test__powixf2(0, 2, 0);
476 try test__powixf2(0, 3, 0);
477 try test__powixf2(0, 4, 0);
478 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
479 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
480
481 try test__powixf2(-0.0, 1, -0.0);
482 try test__powixf2(-0.0, 2, 0);
483 try test__powixf2(-0.0, 3, -0.0);
484 try test__powixf2(-0.0, 4, 0);
485 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
486 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
487
488 try test__powixf2(1, 1, 1);
489 try test__powixf2(1, 2, 1);
490 try test__powixf2(1, 3, 1);
491 try test__powixf2(1, 4, 1);
492 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
493 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
494
495 try test__powixf2(inf_f80, 1, inf_f80);
496 try test__powixf2(inf_f80, 2, inf_f80);
497 try test__powixf2(inf_f80, 3, inf_f80);
498 try test__powixf2(inf_f80, 4, inf_f80);
499 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
500 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);
501
502 try test__powixf2(-inf_f80, 1, -inf_f80);
503 try test__powixf2(-inf_f80, 2, inf_f80);
504 try test__powixf2(-inf_f80, 3, -inf_f80);
505 try test__powixf2(-inf_f80, 4, inf_f80);
506 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
507 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);
508
509 try test__powixf2(0, -1, inf_f80);
510 try test__powixf2(0, -2, inf_f80);
511 try test__powixf2(0, -3, inf_f80);
512 try test__powixf2(0, -4, inf_f80);
513 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
514 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);
515 try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
516
517 try test__powixf2(-0.0, -1, -inf_f80);
518 try test__powixf2(-0.0, -2, inf_f80);
519 try test__powixf2(-0.0, -3, -inf_f80);
520 try test__powixf2(-0.0, -4, inf_f80);
521 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
522 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);
523 try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
524
525 try test__powixf2(1, -1, 1);
526 try test__powixf2(1, -2, 1);
527 try test__powixf2(1, -3, 1);
528 try test__powixf2(1, -4, 1);
529 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
530 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
531 try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
532
533 try test__powixf2(inf_f80, -1, 0);
534 try test__powixf2(inf_f80, -2, 0);
535 try test__powixf2(inf_f80, -3, 0);
536 try test__powixf2(inf_f80, -4, 0);
537 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
538 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
539 try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
540
541 try test__powixf2(-inf_f80, -1, -0.0);
542 try test__powixf2(-inf_f80, -2, 0);
543 try test__powixf2(-inf_f80, -3, -0.0);
544 try test__powixf2(-inf_f80, -4, 0);
545 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
546 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
547 try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
548
549 try test__powixf2(2, 10, 1024.0);
550 try test__powixf2(-2, 10, 1024.0);
551 try test__powixf2(2, -10, 1.0 / 1024.0);
552 try test__powixf2(-2, -10, 1.0 / 1024.0);
553
554 try test__powixf2(2, 19, 524288.0);
555 try test__powixf2(-2, 19, -524288.0);
556 try test__powixf2(2, -19, 1.0 / 524288.0);
557 try test__powixf2(-2, -19, -1.0 / 524288.0);
558
559 try test__powixf2(2, 31, 2147483648.0);
560 try test__powixf2(-2, 31, -2147483648.0);
561 try test__powixf2(2, -31, 1.0 / 2147483648.0);
562 try test__powixf2(-2, -31, -1.0 / 2147483648.0);
466test powi_f128 {
467 const inf_f128 = math.inf(f128);
468 try test_powi_f128(0, 0, 1);
469 try test_powi_f128(1, 0, 1);
470 try test_powi_f128(1.5, 0, 1);
471 try test_powi_f128(2, 0, 1);
472 try test_powi_f128(inf_f128, 0, 1);
473
474 try test_powi_f128(-0.0, 0, 1);
475 try test_powi_f128(-1, 0, 1);
476 try test_powi_f128(-1.5, 0, 1);
477 try test_powi_f128(-2, 0, 1);
478 try test_powi_f128(-inf_f128, 0, 1);
479
480 try test_powi_f128(0, 1, 0);
481 try test_powi_f128(0, 2, 0);
482 try test_powi_f128(0, 3, 0);
483 try test_powi_f128(0, 4, 0);
484 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
485 try test_powi_f128(0, 0x7FFFFFFF, 0);
486
487 try test_powi_f128(-0.0, 1, -0.0);
488 try test_powi_f128(-0.0, 2, 0);
489 try test_powi_f128(-0.0, 3, -0.0);
490 try test_powi_f128(-0.0, 4, 0);
491 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
492 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
493
494 try test_powi_f128(1, 1, 1);
495 try test_powi_f128(1, 2, 1);
496 try test_powi_f128(1, 3, 1);
497 try test_powi_f128(1, 4, 1);
498 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
499 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
500
501 try test_powi_f128(inf_f128, 1, inf_f128);
502 try test_powi_f128(inf_f128, 2, inf_f128);
503 try test_powi_f128(inf_f128, 3, inf_f128);
504 try test_powi_f128(inf_f128, 4, inf_f128);
505 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
506 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);
507
508 try test_powi_f128(-inf_f128, 1, -inf_f128);
509 try test_powi_f128(-inf_f128, 2, inf_f128);
510 try test_powi_f128(-inf_f128, 3, -inf_f128);
511 try test_powi_f128(-inf_f128, 4, inf_f128);
512 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
513 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);
514
515 try test_powi_f128(0, -1, inf_f128);
516 try test_powi_f128(0, -2, inf_f128);
517 try test_powi_f128(0, -3, inf_f128);
518 try test_powi_f128(0, -4, inf_f128);
519 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
520 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);
521 try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
522
523 try test_powi_f128(-0.0, -1, -inf_f128);
524 try test_powi_f128(-0.0, -2, inf_f128);
525 try test_powi_f128(-0.0, -3, -inf_f128);
526 try test_powi_f128(-0.0, -4, inf_f128);
527 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
528 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);
529 try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
530
531 try test_powi_f128(1, -1, 1);
532 try test_powi_f128(1, -2, 1);
533 try test_powi_f128(1, -3, 1);
534 try test_powi_f128(1, -4, 1);
535 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
536 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
537 try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
538
539 try test_powi_f128(inf_f128, -1, 0);
540 try test_powi_f128(inf_f128, -2, 0);
541 try test_powi_f128(inf_f128, -3, 0);
542 try test_powi_f128(inf_f128, -4, 0);
543 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
544 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
545 try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
546
547 try test_powi_f128(-inf_f128, -1, -0.0);
548 try test_powi_f128(-inf_f128, -2, 0);
549 try test_powi_f128(-inf_f128, -3, -0.0);
550 try test_powi_f128(-inf_f128, -4, 0);
551 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
552 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
553 try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
554
555 try test_powi_f128(2, 10, 1024.0);
556 try test_powi_f128(-2, 10, 1024.0);
557 try test_powi_f128(2, -10, 1.0 / 1024.0);
558 try test_powi_f128(-2, -10, 1.0 / 1024.0);
559
560 try test_powi_f128(2, 19, 524288.0);
561 try test_powi_f128(-2, 19, -524288.0);
562 try test_powi_f128(2, -19, 1.0 / 524288.0);
563 try test_powi_f128(-2, -19, -1.0 / 524288.0);
564
565 try test_powi_f128(2, 31, 2147483648.0);
566 try test_powi_f128(-2, 31, -2147483648.0);
567 try test_powi_f128(2, -31, 1.0 / 2147483648.0);
568 try test_powi_f128(-2, -31, -1.0 / 2147483648.0);
563569}
lib/compiler_rt/round.zig+87-50
......@@ -18,19 +18,22 @@ comptime {
1818 symbol(&roundf, "roundf");
1919 symbol(&round, "round");
2020 symbol(&__roundx, "__roundx");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&roundq, "roundf128");
23 }
24 symbol(&roundq, "roundq");
21 symbol(&roundq, "roundf128");
2522 symbol(&roundl, "roundl");
2623}
2724
28pub fn __roundh(x: f16) callconv(.c) f16 {
25fn __roundh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
26 return compiler_rt.f16.toAbi(round_f16(compiler_rt.f16.fromAbi(x)));
27}
28pub fn round_f16(x: f16) f16 {
2929 // TODO: more efficient implementation
30 return @floatCast(roundf(x));
30 return @floatCast(round_f32(x));
3131}
3232
33pub fn roundf(x_: f32) callconv(.c) f32 {
33fn roundf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
34 return compiler_rt.f32.toAbi(round_f32(compiler_rt.f32.fromAbi(x)));
35}
36pub fn round_f32(x_: f32) f32 {
3437 const f32_toint = 1.0 / math.floatEps(f32);
3538
3639 var x = x_;
......@@ -65,7 +68,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 {
6568 }
6669}
6770
68pub fn round(x_: f64) callconv(.c) f64 {
71fn round(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
72 return compiler_rt.f64.toAbi(round_f64(compiler_rt.f64.fromAbi(x)));
73}
74pub fn round_f64(x_: f64) f64 {
6975 const f64_toint = 1.0 / math.floatEps(f64);
7076
7177 var x = x_;
......@@ -100,12 +106,18 @@ pub fn round(x_: f64) callconv(.c) f64 {
100106 }
101107}
102108
103pub fn __roundx(x: f80) callconv(.c) f80 {
109fn __roundx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
110 return compiler_rt.f80.toAbi(round_f80(compiler_rt.f80.fromAbi(x)));
111}
112pub fn round_f80(x: f80) f80 {
104113 // TODO: more efficient implementation
105 return @floatCast(roundq(x));
114 return @floatCast(round_f128(x));
106115}
107116
108pub fn roundq(x_: f128) callconv(.c) f128 {
117fn roundq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
118 return compiler_rt.f128.toAbi(round_f128(compiler_rt.f128.fromAbi(x)));
119}
120pub fn round_f128(x_: f128) f128 {
109121 const f128_toint = 1.0 / math.floatEps(f128);
110122
111123 var x = x_;
......@@ -142,54 +154,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 {
142154
143155pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble {
144156 switch (@typeInfo(c_longdouble).float.bits) {
145 64 => return round(x),
146 80 => return __roundx(x),
147 128 => return roundq(x),
148 else => @compileError("unreachable"),
157 64 => return round_f64(x),
158 80 => return round_f80(x),
159 128 => return round_f128(x),
160 else => comptime unreachable,
149161 }
150162}
151163
152test "round32" {
153 try expect(roundf(1.3) == 1.0);
154 try expect(roundf(-1.3) == -1.0);
155 try expect(roundf(0.2) == 0.0);
156 try expect(roundf(1.8) == 2.0);
157}
158
159test "round64" {
160 try expect(round(1.3) == 1.0);
161 try expect(round(-1.3) == -1.0);
162 try expect(round(0.2) == 0.0);
163 try expect(round(1.8) == 2.0);
164test round_f16 {
165 try expect(round_f16(1.3) == 1.0);
166 try expect(round_f16(-1.3) == -1.0);
167 try expect(round_f16(1.8) == 2.0);
168 try expect(round_f16(-1.8) == -2.0);
169 try expect(math.isPositiveZero(round_f16(0.2)));
170 try expect(math.isNegativeZero(round_f16(-0.2)));
171 try expect(math.isPositiveZero(round_f16(0.0)));
172 try expect(math.isNegativeZero(round_f16(-0.0)));
173 try expect(math.isPositiveInf(round_f16(math.inf(f32))));
174 try expect(math.isNegativeInf(round_f16(-math.inf(f32))));
175 try expect(math.isNan(round_f16(math.nan(f32))));
164176}
165177
166test "round128" {
167 try expect(roundq(1.3) == 1.0);
168 try expect(roundq(-1.3) == -1.0);
169 try expect(roundq(0.2) == 0.0);
170 try expect(roundq(1.8) == 2.0);
178test round_f32 {
179 try expect(round_f32(1.3) == 1.0);
180 try expect(round_f32(-1.3) == -1.0);
181 try expect(round_f32(1.8) == 2.0);
182 try expect(round_f32(-1.8) == -2.0);
183 try expect(math.isPositiveZero(round_f32(0.2)));
184 try expect(math.isNegativeZero(round_f32(-0.2)));
185 try expect(math.isPositiveZero(round_f32(0.0)));
186 try expect(math.isNegativeZero(round_f32(-0.0)));
187 try expect(math.isPositiveInf(round_f32(math.inf(f32))));
188 try expect(math.isNegativeInf(round_f32(-math.inf(f32))));
189 try expect(math.isNan(round_f32(math.nan(f32))));
171190}
172191
173test "round32.special" {
174 try expect(roundf(0.0) == 0.0);
175 try expect(roundf(-0.0) == -0.0);
176 try expect(math.isPositiveInf(roundf(math.inf(f32))));
177 try expect(math.isNegativeInf(roundf(-math.inf(f32))));
178 try expect(math.isNan(roundf(math.nan(f32))));
192test round_f64 {
193 try expect(round_f64(1.3) == 1.0);
194 try expect(round_f64(-1.3) == -1.0);
195 try expect(round_f64(1.8) == 2.0);
196 try expect(round_f64(-1.8) == -2.0);
197 try expect(math.isPositiveZero(round_f64(0.2)));
198 try expect(math.isNegativeZero(round_f64(-0.2)));
199 try expect(math.isPositiveZero(round_f64(0.0)));
200 try expect(math.isNegativeZero(round_f64(-0.0)));
201 try expect(math.isPositiveInf(round_f64(math.inf(f64))));
202 try expect(math.isNegativeInf(round_f64(-math.inf(f64))));
203 try expect(math.isNan(round_f64(math.nan(f64))));
179204}
180205
181test "round64.special" {
182 try expect(round(0.0) == 0.0);
183 try expect(round(-0.0) == -0.0);
184 try expect(math.isPositiveInf(round(math.inf(f64))));
185 try expect(math.isNegativeInf(round(-math.inf(f64))));
186 try expect(math.isNan(round(math.nan(f64))));
206test round_f80 {
207 try expect(round_f80(1.3) == 1.0);
208 try expect(round_f80(-1.3) == -1.0);
209 try expect(round_f80(1.8) == 2.0);
210 try expect(round_f80(-1.8) == -2.0);
211 try expect(math.isPositiveZero(round_f80(0.2)));
212 try expect(math.isNegativeZero(round_f80(-0.2)));
213 try expect(math.isPositiveZero(round_f80(0.0)));
214 try expect(math.isNegativeZero(round_f80(-0.0)));
215 try expect(math.isPositiveInf(round_f80(math.inf(f64))));
216 try expect(math.isNegativeInf(round_f80(-math.inf(f64))));
217 try expect(math.isNan(round_f80(math.nan(f64))));
187218}
188219
189test "round128.special" {
190 try expect(roundq(0.0) == 0.0);
191 try expect(roundq(-0.0) == -0.0);
192 try expect(math.isPositiveInf(roundq(math.inf(f128))));
193 try expect(math.isNegativeInf(roundq(-math.inf(f128))));
194 try expect(math.isNan(roundq(math.nan(f128))));
220test round_f128 {
221 try expect(round_f128(1.3) == 1.0);
222 try expect(round_f128(-1.3) == -1.0);
223 try expect(round_f128(1.8) == 2.0);
224 try expect(round_f128(-1.8) == -2.0);
225 try expect(math.isPositiveZero(round_f128(0.2)));
226 try expect(math.isNegativeZero(round_f128(-0.2)));
227 try expect(math.isPositiveZero(round_f128(0.0)));
228 try expect(math.isNegativeZero(round_f128(-0.0)));
229 try expect(math.isPositiveInf(round_f128(math.inf(f128))));
230 try expect(math.isNegativeInf(round_f128(-math.inf(f128))));
231 try expect(math.isNan(round_f128(math.nan(f128))));
195232}
lib/compiler_rt/sin.zig+66-53
......@@ -13,31 +13,34 @@ const expect = std.testing.expect;
1313const expectApproxEqAbs = std.testing.expectApproxEqAbs;
1414
1515const compiler_rt = @import("../compiler_rt.zig");
16const symbol = @import("../compiler_rt.zig").symbol;
16const symbol = compiler_rt.symbol;
1717const trig = @import("trig.zig");
1818const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
1919const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
2020const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
2222comptime {
23 symbol(&sinh, "__sinh");
24 symbol(&sinl, "__sinl");
23 symbol(&__sinh, "__sinh");
2524 symbol(&sinf, "sinf");
2625 symbol(&sin, "sin");
27 symbol(&sinx, "__sinx");
28 if (compiler_rt.want_ppc_abi) {
29 symbol(&sinq, "sinf128");
30 }
31 symbol(&sinq, "sinq");
26 symbol(&__sinx, "__sinx");
27 symbol(&sinq, "sinf128");
3228 symbol(&sinl, "sinl");
29 symbol(&sinl, "__sinl"); // required by musl
3330}
3431
35pub fn sinh(x: f16) callconv(.c) f16 {
32fn __sinh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
33 return compiler_rt.f16.toAbi(sin_f16(compiler_rt.f16.fromAbi(x)));
34}
35pub fn sin_f16(x: f16) f16 {
3636 // TODO: more efficient implementation
37 return @floatCast(sinf(x));
37 return @floatCast(sin_f32(x));
3838}
3939
40pub fn sinf(x: f32) callconv(.c) f32 {
40fn sinf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
41 return compiler_rt.f32.toAbi(sin_f32(compiler_rt.f32.fromAbi(x)));
42}
43pub fn sin_f32(x: f32) f32 {
4144 // Small multiples of pi/2 rounded to double precision.
4245 const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
4346 const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
......@@ -98,7 +101,10 @@ pub fn sinf(x: f32) callconv(.c) f32 {
98101 };
99102}
100103
101pub fn sin(x: f64) callconv(.c) f64 {
104fn sin(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
105 return compiler_rt.f64.toAbi(sin_f64(compiler_rt.f64.fromAbi(x)));
106}
107pub fn sin_f64(x: f64) f64 {
102108 var ix = @as(u64, @bitCast(x)) >> 32;
103109 ix &= 0x7fffffff;
104110
......@@ -133,7 +139,10 @@ pub fn sin(x: f64) callconv(.c) f64 {
133139 };
134140}
135141
136fn sinx(x: f80) callconv(.c) f80 {
142fn __sinx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
143 return compiler_rt.f80.toAbi(sin_f80(compiler_rt.f80.fromAbi(x)));
144}
145pub fn sin_f80(x: f80) f80 {
137146 const se = ld.signExponent(x) & 0x7fff;
138147 if (se == 0x7fff) {
139148 return x - x;
......@@ -160,7 +169,10 @@ fn sinx(x: f80) callconv(.c) f80 {
160169 };
161170}
162171
163pub fn sinq(x: f128) callconv(.c) f128 {
172fn sinq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
173 return compiler_rt.f128.toAbi(sin_f128(compiler_rt.f128.fromAbi(x)));
174}
175pub fn sin_f128(x: f128) f128 {
164176 const se = ld.signExponent(x) & 0x7fff;
165177 if (se == 0x7fff) {
166178 return x - x;
......@@ -189,20 +201,21 @@ pub fn sinq(x: f128) callconv(.c) f128 {
189201
190202pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble {
191203 switch (@typeInfo(c_longdouble).float.bits) {
192 64 => return sin(x),
193 80 => return sinx(x),
194 128 => return sinq(x),
195 else => @compileError("unreachable"),
204 64 => return sin_f64(x),
205 80 => return sin_f80(x),
206 128 => return sin_f128(x),
207 else => comptime unreachable,
196208 }
197209}
198210
199211fn testSinSpecial(comptime T: type) !void {
200212 const f = switch (T) {
201 f32 => sinf,
202 f64 => sin,
203 f80 => sinx,
204 f128 => sinq,
205 else => @compileError("unimplemented"),
213 f16 => sin_f16,
214 f32 => sin_f32,
215 f64 => sin_f64,
216 f80 => sin_f80,
217 f128 => sin_f128,
218 else => comptime unreachable,
206219 };
207220
208221 try expect(math.isPositiveZero(f(0.0)));
......@@ -214,13 +227,13 @@ fn testSinSpecial(comptime T: type) !void {
214227
215228test "sin32.normal" {
216229 const epsilon = math.floatEps(f32);
217 try expectApproxEqAbs(@as(f32, 0.0), sinf(0.0), epsilon);
218 try expectApproxEqAbs(@as(f32, 0.19866933), sinf(0.2), epsilon);
219 try expectApproxEqAbs(@as(f32, 0.77851737), sinf(0.8923), epsilon);
220 try expectApproxEqAbs(@as(f32, 0.997495), sinf(1.5), epsilon);
221 try expectApproxEqAbs(@as(f32, -0.997495), sinf(-1.5), epsilon);
222 try expectApproxEqAbs(@as(f32, -0.24654257), sinf(37.45), epsilon);
223 try expectApproxEqAbs(@as(f32, 0.9161657), sinf(89.123), epsilon);
230 try expectApproxEqAbs(@as(f32, 0.0), sin_f32(0.0), epsilon);
231 try expectApproxEqAbs(@as(f32, 0.19866933), sin_f32(0.2), epsilon);
232 try expectApproxEqAbs(@as(f32, 0.77851737), sin_f32(0.8923), epsilon);
233 try expectApproxEqAbs(@as(f32, 0.997495), sin_f32(1.5), epsilon);
234 try expectApproxEqAbs(@as(f32, -0.997495), sin_f32(-1.5), epsilon);
235 try expectApproxEqAbs(@as(f32, -0.24654257), sin_f32(37.45), epsilon);
236 try expectApproxEqAbs(@as(f32, 0.9161657), sin_f32(89.123), epsilon);
224237}
225238
226239test "sin32.special" {
......@@ -229,13 +242,13 @@ test "sin32.special" {
229242
230243test "sin64.normal" {
231244 const epsilon = math.floatEps(f64);
232 try expectApproxEqAbs(@as(f64, 0.0), sin(0.0), epsilon);
233 try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin(0.2), epsilon);
234 try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin(0.8923), epsilon);
235 try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin(1.5), epsilon);
236 try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin(-1.5), epsilon);
237 try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin(37.45), epsilon);
238 try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin(89.123), epsilon);
245 try expectApproxEqAbs(@as(f64, 0.0), sin_f64(0.0), epsilon);
246 try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin_f64(0.2), epsilon);
247 try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin_f64(0.8923), epsilon);
248 try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin_f64(1.5), epsilon);
249 try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin_f64(-1.5), epsilon);
250 try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin_f64(37.45), epsilon);
251 try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin_f64(89.123), epsilon);
239252}
240253
241254test "sin64.special" {
......@@ -244,13 +257,13 @@ test "sin64.special" {
244257
245258test "sin80.normal" {
246259 const epsilon = math.floatEps(f80);
247 try expectApproxEqAbs(@as(f80, 0.0), sinx(0.0), epsilon);
248 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sinx(0.2), epsilon);
249 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sinx(0.8923), epsilon);
250 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sinx(1.5), epsilon);
251 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sinx(-1.5), epsilon);
252 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sinx(37.45), epsilon);
253 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sinx(89.123), epsilon);
260 try expectApproxEqAbs(@as(f80, 0.0), sin_f80(0.0), epsilon);
261 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sin_f80(0.2), epsilon);
262 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sin_f80(0.8923), epsilon);
263 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sin_f80(1.5), epsilon);
264 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sin_f80(-1.5), epsilon);
265 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sin_f80(37.45), epsilon);
266 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sin_f80(89.123), epsilon);
254267}
255268
256269test "sin80.special" {
......@@ -259,13 +272,13 @@ test "sin80.special" {
259272
260273test "sin128.normal" {
261274 const epsilon = math.floatEps(f128);
262 try expectApproxEqAbs(@as(f128, 0.0), sinq(0.0), epsilon);
263 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sinq(0.2), epsilon);
264 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sinq(0.8923), epsilon);
265 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sinq(1.5), epsilon);
266 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sinq(-1.5), epsilon);
267 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sinq(37.45), epsilon);
268 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sinq(89.123), epsilon);
275 try expectApproxEqAbs(@as(f128, 0.0), sin_f128(0.0), epsilon);
276 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sin_f128(0.2), epsilon);
277 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sin_f128(0.8923), epsilon);
278 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sin_f128(1.5), epsilon);
279 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sin_f128(-1.5), epsilon);
280 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sin_f128(37.45), epsilon);
281 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sin_f128(89.123), epsilon);
269282}
270283
271284test "sin128.special" {
......@@ -274,10 +287,10 @@ test "sin128.special" {
274287
275288test "sin32 #9901" {
276289 const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000));
277 _ = sinf(float);
290 _ = sin_f32(float);
278291}
279292
280293test "sin64 #9901" {
281294 const float: f64 = @bitCast(@as(u64, 0b1111111101000001000000001111110111111111100000000000000000000001));
282 _ = sin(float);
295 _ = sin_f64(float);
283296}
lib/compiler_rt/sincos.zig+125-181
......@@ -18,23 +18,27 @@ comptime {
1818 symbol(&sincosf, "sincosf");
1919 symbol(&sincos, "sincos");
2020 symbol(&sincosx, "__sincosx");
21 if (compiler_rt.want_ppc_abi) {
22 symbol(&sincosq, "sincosf128");
23 }
24 symbol(&sincosq, "sincosq");
21 symbol(&sincosq, "sincosf128");
2522 symbol(&sincosl, "sincosl");
2623}
2724
28pub fn sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.c) void {
25fn sincosh(x: compiler_rt.f16.Abi, r_sin: *compiler_rt.f16.Abi, r_cos: *compiler_rt.f16.Abi) callconv(.c) void {
26 const s, const c = sincos_f16(compiler_rt.f16.fromAbi(x));
27 r_sin.* = compiler_rt.f16.toAbi(s);
28 r_cos.* = compiler_rt.f16.toAbi(c);
29}
30pub fn sincos_f16(x: f16) struct { f16, f16 } {
2931 // TODO: more efficient implementation
30 var big_sin: f32 = undefined;
31 var big_cos: f32 = undefined;
32 sincosf(x, &big_sin, &big_cos);
33 r_sin.* = @as(f16, @floatCast(big_sin));
34 r_cos.* = @as(f16, @floatCast(big_cos));
32 const s, const c = sincos_f32(x);
33 return .{ @floatCast(s), @floatCast(c) };
3534}
3635
37pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
36fn sincosf(x: compiler_rt.f32.Abi, r_sin: *compiler_rt.f32.Abi, r_cos: *compiler_rt.f32.Abi) callconv(.c) void {
37 const s, const c = sincos_f32(compiler_rt.f32.fromAbi(x));
38 r_sin.* = compiler_rt.f32.toAbi(s);
39 r_cos.* = compiler_rt.f32.toAbi(c);
40}
41pub fn sincos_f32(x: f32) struct { f32, f32 } {
3842 const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
3943 const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
4044 const sc3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2
......@@ -56,13 +60,9 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
5660 mem.doNotOptimizeAway(x + 0x1p120);
5761 }
5862 }
59 r_sin.* = x;
60 r_cos.* = 1.0;
61 return;
63 return .{ x, 1.0 };
6264 }
63 r_sin.* = trig.sindf(x);
64 r_cos.* = trig.cosdf(x);
65 return;
65 return .{ trig.sindf(x), trig.cosdf(x) };
6666 }
6767
6868 // |x| ~<= 5*pi/4
......@@ -70,18 +70,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
7070 // |x| ~<= 3pi/4
7171 if (ix <= 0x4016cbe3) {
7272 if (sign) {
73 r_sin.* = -trig.cosdf(x + sc1pio2);
74 r_cos.* = trig.sindf(x + sc1pio2);
73 return .{ -trig.cosdf(x + sc1pio2), trig.sindf(x + sc1pio2) };
7574 } else {
76 r_sin.* = trig.cosdf(sc1pio2 - x);
77 r_cos.* = trig.sindf(sc1pio2 - x);
75 return .{ trig.cosdf(sc1pio2 - x), trig.sindf(sc1pio2 - x) };
7876 }
79 return;
8077 }
8178 // -sin(x+c) is not correct if x+c could be 0: -0 vs +0
82 r_sin.* = -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2);
83 r_cos.* = -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2);
84 return;
79 return .{
80 -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2),
81 -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2),
82 };
8583 }
8684
8785 // |x| ~<= 9*pi/4
......@@ -89,25 +87,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
8987 // |x| ~<= 7*pi/4
9088 if (ix <= 0x40afeddf) {
9189 if (sign) {
92 r_sin.* = trig.cosdf(x + sc3pio2);
93 r_cos.* = -trig.sindf(x + sc3pio2);
90 return .{ trig.cosdf(x + sc3pio2), -trig.sindf(x + sc3pio2) };
9491 } else {
95 r_sin.* = -trig.cosdf(x - sc3pio2);
96 r_cos.* = trig.sindf(x - sc3pio2);
92 return .{ -trig.cosdf(x - sc3pio2), trig.sindf(x - sc3pio2) };
9793 }
98 return;
9994 }
100 r_sin.* = trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2);
101 r_cos.* = trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2);
102 return;
95 return .{
96 trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2),
97 trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2),
98 };
10399 }
104100
105101 // sin(Inf or NaN) is NaN
106102 if (ix >= 0x7f800000) {
107103 const result = x - x;
108 r_sin.* = result;
109 r_cos.* = result;
110 return;
104 return .{ result, result };
111105 }
112106
113107 // general argument reduction needed
......@@ -115,27 +109,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
115109 const n = rem_pio2f(x, &y);
116110 const s = trig.sindf(y);
117111 const c = trig.cosdf(y);
118 switch (n & 3) {
119 0 => {
120 r_sin.* = s;
121 r_cos.* = c;
122 },
123 1 => {
124 r_sin.* = c;
125 r_cos.* = -s;
126 },
127 2 => {
128 r_sin.* = -s;
129 r_cos.* = -c;
130 },
131 else => {
132 r_sin.* = -c;
133 r_cos.* = s;
134 },
135 }
112 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
113 0 => .{ s, c },
114 1 => .{ c, -s },
115 2 => .{ -s, -c },
116 3 => .{ -c, s },
117 };
136118}
137119
138pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
120fn sincos(x: compiler_rt.f64.Abi, r_sin: *compiler_rt.f64.Abi, r_cos: *compiler_rt.f64.Abi) callconv(.c) void {
121 const s, const c = sincos_f64(compiler_rt.f64.fromAbi(x));
122 r_sin.* = compiler_rt.f64.toAbi(s);
123 r_cos.* = compiler_rt.f64.toAbi(c);
124}
125pub fn sincos_f64(x: f64) struct { f64, f64 } {
139126 const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff;
140127
141128 // |x| ~< pi/4
......@@ -150,21 +137,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
150137 mem.doNotOptimizeAway(x + 0x1p120);
151138 }
152139 }
153 r_sin.* = x;
154 r_cos.* = 1.0;
155 return;
140 return .{ x, 1.0 };
156141 }
157 r_sin.* = trig.sin(x, 0.0, 0);
158 r_cos.* = trig.cos(x, 0.0);
159 return;
142 return .{ trig.sin(x, 0.0, 0), trig.cos(x, 0.0) };
160143 }
161144
162145 // sincos(Inf or NaN) is NaN
163146 if (ix >= 0x7ff00000) {
164147 const result = x - x;
165 r_sin.* = result;
166 r_cos.* = result;
167 return;
148 return .{ result, result };
168149 }
169150
170151 // argument reduction needed
......@@ -172,33 +153,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
172153 const n = rem_pio2(x, &y);
173154 const s = trig.sin(y[0], y[1], 1);
174155 const c = trig.cos(y[0], y[1]);
175 switch (n & 3) {
176 0 => {
177 r_sin.* = s;
178 r_cos.* = c;
179 },
180 1 => {
181 r_sin.* = c;
182 r_cos.* = -s;
183 },
184 2 => {
185 r_sin.* = -s;
186 r_cos.* = -c;
187 },
188 else => {
189 r_sin.* = -c;
190 r_cos.* = s;
191 },
192 }
156 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
157 0 => .{ s, c },
158 1 => .{ c, -s },
159 2 => .{ -s, -c },
160 3 => .{ -c, s },
161 };
193162}
194163
195pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void {
164fn sincosx(x: compiler_rt.f80.Abi, r_sin: *compiler_rt.f80.Abi, r_cos: *compiler_rt.f80.Abi) callconv(.c) void {
165 const s, const c = sincos_f80(compiler_rt.f80.fromAbi(x));
166 r_sin.* = compiler_rt.f80.toAbi(s);
167 r_cos.* = compiler_rt.f80.toAbi(c);
168}
169pub fn sincos_f80(x: f80) struct { f80, f80 } {
196170 const se = ld.signExponent(x) & 0x7fff;
197171 if (se == 0x7fff) {
198172 const result = x - x;
199 r_sin.* = result;
200 r_cos.* = result;
201 return;
173 return .{ result, result };
202174 }
203175
204176 if (@abs(x) < trig.pi_4) {
......@@ -207,47 +179,34 @@ pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void {
207179 if (compiler_rt.want_float_exceptions and se == 0) {
208180 mem.doNotOptimizeAway(x * 0x1p-120);
209181 }
210 r_sin.* = x;
211182 // raise inexact if x!=0
212 r_cos.* = 1.0 + x;
213 return;
183 return .{ x, 1.0 + x };
214184 }
215 r_sin.* = trig.sinx(x, 0.0, 0);
216 r_cos.* = trig.cosx(x, 0.0);
217 return;
185 return .{ trig.sinx(x, 0.0, 0), trig.cosx(x, 0.0) };
218186 }
219187
220188 var y: [2]f80 = undefined;
221189 const n = rem_pio2l(f80, x, &y);
222190 const s = trig.sinx(y[0], y[1], 1);
223191 const c = trig.cosx(y[0], y[1]);
224 switch (n & 3) {
225 0 => {
226 r_sin.* = s;
227 r_cos.* = c;
228 },
229 1 => {
230 r_sin.* = c;
231 r_cos.* = -s;
232 },
233 2 => {
234 r_sin.* = -s;
235 r_cos.* = -c;
236 },
237 else => {
238 r_sin.* = -c;
239 r_cos.* = s;
240 },
241 }
192 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
193 0 => .{ s, c },
194 1 => .{ c, -s },
195 2 => .{ -s, -c },
196 3 => .{ -c, s },
197 };
242198}
243199
244pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void {
200fn sincosq(x: compiler_rt.f128.Abi, r_sin: *compiler_rt.f128.Abi, r_cos: *compiler_rt.f128.Abi) callconv(.c) void {
201 const s, const c = sincos_f128(compiler_rt.f128.fromAbi(x));
202 r_sin.* = compiler_rt.f128.toAbi(s);
203 r_cos.* = compiler_rt.f128.toAbi(c);
204}
205pub fn sincos_f128(x: f128) struct { f128, f128 } {
245206 const se = ld.signExponent(x) & 0x7fff;
246207 if (se == 0x7fff) {
247208 const result = x - x;
248 r_sin.* = result;
249 r_cos.* = result;
250 return;
209 return .{ result, result };
251210 }
252211
253212 if (@abs(x) < trig.pi_4) {
......@@ -256,78 +215,63 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void {
256215 if (compiler_rt.want_float_exceptions and se == 0) {
257216 mem.doNotOptimizeAway(x * 0x1p-120);
258217 }
259 r_sin.* = x;
260218 // raise inexact if x!=0
261 r_cos.* = 1.0 + x;
262 return;
219 return .{ x, 1.0 + x };
263220 }
264 r_sin.* = trig.sinq(x, 0.0, 0);
265 r_cos.* = trig.cosq(x, 0.0);
266 return;
221 return .{ trig.sinq(x, 0.0, 0), trig.cosq(x, 0.0) };
267222 }
268223
269224 var y: [2]f128 = undefined;
270225 const n = rem_pio2l(f128, x, &y);
271226 const s = trig.sinq(y[0], y[1], 1);
272227 const c = trig.cosq(y[0], y[1]);
273 switch (n & 3) {
274 0 => {
275 r_sin.* = s;
276 r_cos.* = c;
277 },
278 1 => {
279 r_sin.* = c;
280 r_cos.* = -s;
281 },
282 2 => {
283 r_sin.* = -s;
284 r_cos.* = -c;
285 },
286 else => {
287 r_sin.* = -c;
288 r_cos.* = s;
289 },
290 }
228 return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) {
229 0 => .{ s, c },
230 1 => .{ c, -s },
231 2 => .{ -s, -c },
232 3 => .{ -c, s },
233 };
291234}
292235
293236pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void {
294 switch (@typeInfo(c_longdouble).float.bits) {
295 64 => return sincos(x, r_sin, r_cos),
296 80 => return sincosx(x, r_sin, r_cos),
297 128 => return sincosq(x, r_sin, r_cos),
298 else => @compileError("unreachable"),
299 }
237 r_sin.*, r_cos.* = switch (@typeInfo(c_longdouble).float.bits) {
238 64 => sincos_f64(x),
239 80 => sincos_f80(x),
240 128 => sincos_f128(x),
241 else => comptime unreachable,
242 };
300243}
301244
302245fn testSincosSpecial(comptime T: type) !void {
303246 const f = switch (T) {
304 f32 => sincosf,
305 f64 => sincos,
306 f80 => sincosx,
307 f128 => sincosq,
247 f16 => sincos_f16,
248 f32 => sincos_f32,
249 f64 => sincos_f64,
250 f80 => sincos_f80,
251 f128 => sincos_f128,
308252 else => @compileError("unimplemented"),
309253 };
310254
311255 var s: T = undefined;
312256 var c: T = undefined;
313257
314 f(0.0, &s, &c);
258 s, c = f(0.0);
315259 try expect(math.isPositiveZero(s));
316260 try expect(c == 1.0);
317261
318 f(-0.0, &s, &c);
262 s, c = f(-0.0);
319263 try expect(math.isNegativeZero(s));
320264 try expect(c == 1.0);
321265
322 f(math.inf(T), &s, &c);
266 s, c = f(math.inf(T));
323267 try expect(math.isNan(s));
324268 try expect(math.isNan(c));
325269
326 f(-math.inf(T), &s, &c);
270 s, c = f(-math.inf(T));
327271 try expect(math.isNan(s));
328272 try expect(math.isNan(c));
329273
330 f(math.nan(T), &s, &c);
274 s, c = f(math.nan(T));
331275 try expect(math.isNan(s));
332276 try expect(math.isNan(c));
333277}
......@@ -337,31 +281,31 @@ test "sincos32.normal" {
337281 var s: f32 = undefined;
338282 var c: f32 = undefined;
339283
340 sincosf(0.0, &s, &c);
284 s, c = sincos_f32(0.0);
341285 try expectApproxEqAbs(@as(f32, 0.0), s, epsilon);
342286 try expectApproxEqAbs(@as(f32, 1.0), c, epsilon);
343287
344 sincosf(0.2, &s, &c);
288 s, c = sincos_f32(0.2);
345289 try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon);
346290 try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon);
347291
348 sincosf(0.8923, &s, &c);
292 s, c = sincos_f32(0.8923);
349293 try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon);
350294 try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon);
351295
352 sincosf(1.5, &s, &c);
296 s, c = sincos_f32(1.5);
353297 try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon);
354298 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);
355299
356 sincosf(-1.5, &s, &c);
300 s, c = sincos_f32(-1.5);
357301 try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon);
358302 try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon);
359303
360 sincosf(37.45, &s, &c);
304 s, c = sincos_f32(37.45);
361305 try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon);
362306 try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon);
363307
364 sincosf(89.123, &s, &c);
308 s, c = sincos_f32(89.123);
365309 try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon);
366310 try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon);
367311}
......@@ -375,31 +319,31 @@ test "sincos64.normal" {
375319 var s: f64 = undefined;
376320 var c: f64 = undefined;
377321
378 sincos(0.0, &s, &c);
322 s, c = sincos_f64(0.0);
379323 try expectApproxEqAbs(@as(f64, 0.0), s, epsilon);
380324 try expectApproxEqAbs(@as(f64, 1.0), c, epsilon);
381325
382 sincos(0.2, &s, &c);
326 s, c = sincos_f64(0.2);
383327 try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon);
384328 try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon);
385329
386 sincos(0.8923, &s, &c);
330 s, c = sincos_f64(0.8923);
387331 try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon);
388332 try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon);
389333
390 sincos(1.5, &s, &c);
334 s, c = sincos_f64(1.5);
391335 try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon);
392336 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);
393337
394 sincos(-1.5, &s, &c);
338 s, c = sincos_f64(-1.5);
395339 try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon);
396340 try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon);
397341
398 sincos(37.45, &s, &c);
342 s, c = sincos_f64(37.45);
399343 try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon);
400344 try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon);
401345
402 sincos(89.123, &s, &c);
346 s, c = sincos_f64(89.123);
403347 try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon);
404348 try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon);
405349}
......@@ -413,31 +357,31 @@ test "sincos80.normal" {
413357 var s: f80 = undefined;
414358 var c: f80 = undefined;
415359
416 sincosx(0.0, &s, &c);
360 s, c = sincos_f80(0.0);
417361 try expectApproxEqAbs(@as(f80, 0.0), s, epsilon);
418362 try expectApproxEqAbs(@as(f80, 1.0), c, epsilon);
419363
420 sincosx(0.2, &s, &c);
364 s, c = sincos_f80(0.2);
421365 try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon);
422366 try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon);
423367
424 sincosx(0.8923, &s, &c);
368 s, c = sincos_f80(0.8923);
425369 try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon);
426370 try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon);
427371
428 sincosx(1.5, &s, &c);
372 s, c = sincos_f80(1.5);
429373 try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon);
430374 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);
431375
432 sincosx(-1.5, &s, &c);
376 s, c = sincos_f80(-1.5);
433377 try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon);
434378 try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon);
435379
436 sincosx(37.45, &s, &c);
380 s, c = sincos_f80(37.45);
437381 try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon);
438382 try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon);
439383
440 sincosx(89.123, &s, &c);
384 s, c = sincos_f80(89.123);
441385 try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon);
442386 try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon);
443387}
......@@ -451,31 +395,31 @@ test "sincos128.normal" {
451395 var s: f128 = undefined;
452396 var c: f128 = undefined;
453397
454 sincosq(0.0, &s, &c);
398 s, c = sincos_f128(0.0);
455399 try expectApproxEqAbs(@as(f128, 0.0), s, epsilon);
456400 try expectApproxEqAbs(@as(f128, 1.0), c, epsilon);
457401
458 sincosq(0.2, &s, &c);
402 s, c = sincos_f128(0.2);
459403 try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon);
460404 try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon);
461405
462 sincosq(0.8923, &s, &c);
406 s, c = sincos_f128(0.8923);
463407 try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon);
464408 try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon);
465409
466 sincosq(1.5, &s, &c);
410 s, c = sincos_f128(1.5);
467411 try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon);
468412 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);
469413
470 sincosq(-1.5, &s, &c);
414 s, c = sincos_f128(-1.5);
471415 try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon);
472416 try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon);
473417
474 sincosq(37.45, &s, &c);
418 s, c = sincos_f128(37.45);
475419 try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon);
476420 try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon);
477421
478 sincosq(89.123, &s, &c);
422 s, c = sincos_f128(89.123);
479423 try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon);
480424 try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon);
481425}
lib/compiler_rt/sqrt.zig+150-137
......@@ -17,18 +17,19 @@ comptime {
1717 symbol(&sqrtf, "sqrtf");
1818 symbol(&sqrt, "sqrt");
1919 symbol(&__sqrtx, "__sqrtx");
20 if (compiler_rt.want_ppc_abi) {
21 symbol(&sqrtq, "sqrtf128");
22 } else if (compiler_rt.want_sparc64_abi) {
20 symbol(&sqrtq, "sqrtf128");
21 if (compiler_rt.want_sparc64_abi) {
2322 symbol(&_Qp_sqrt, "_Qp_sqrt");
2423 } else if (compiler_rt.want_sparc32_abi) {
2524 symbol(&sqrtq, "_Q_sqrt");
2625 }
27 symbol(&sqrtq, "sqrtq");
2826 symbol(&sqrtl, "sqrtl");
2927}
3028
31pub fn __sqrth(x: f16) callconv(.c) f16 {
29fn __sqrth(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
30 return compiler_rt.f16.toAbi(sqrt_f16(compiler_rt.f16.fromAbi(x)));
31}
32pub fn sqrt_f16(x: f16) f16 {
3233 var ix: u16 = @bitCast(x);
3334 var top = ix >> 10;
3435
......@@ -93,7 +94,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 {
9394 return y;
9495}
9596
96pub fn sqrtf(x: f32) callconv(.c) f32 {
97fn sqrtf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
98 return compiler_rt.f32.toAbi(sqrt_f32(compiler_rt.f32.fromAbi(x)));
99}
100pub fn sqrt_f32(x: f32) f32 {
97101 var ix: u32 = @bitCast(x);
98102
99103 if (ix < @as(u32, @bitCast(@as(f32, 0x1p-126))) or @as(u32, @bitCast(std.math.inf(f32))) <= ix) {
......@@ -147,7 +151,10 @@ pub fn sqrtf(x: f32) callconv(.c) f32 {
147151 return y + t;
148152}
149153
150pub fn sqrt(x: f64) callconv(.c) f64 {
154fn sqrt(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
155 return compiler_rt.f64.toAbi(sqrt_f64(compiler_rt.f64.fromAbi(x)));
156}
157pub fn sqrt_f64(x: f64) f64 {
151158 var ix: u64 = @bitCast(x);
152159 var top = ix >> 52;
153160
......@@ -284,7 +291,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 {
284291 return y;
285292}
286293
287pub fn __sqrtx(x: f80) callconv(.c) f80 {
294fn __sqrtx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
295 return compiler_rt.f80.toAbi(sqrt_f80(compiler_rt.f80.fromAbi(x)));
296}
297pub fn sqrt_f80(x: f80) f80 {
288298 var ix: u80 = @bitCast(x);
289299 var top = ix >> 64;
290300
......@@ -381,7 +391,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 {
381391 return y;
382392}
383393
384pub fn sqrtq(x: f128) callconv(.c) f128 {
394fn sqrtq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
395 return compiler_rt.f128.toAbi(sqrt_f128(compiler_rt.f128.fromAbi(x)));
396}
397pub fn sqrt_f128(x: f128) f128 {
385398 var ix: u128 = @bitCast(x);
386399 var top = ix >> 112;
387400
......@@ -483,10 +496,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void {
483496
484497pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble {
485498 switch (@typeInfo(c_longdouble).float.bits) {
486 64 => return sqrt(x),
487 80 => return __sqrtx(x),
488 128 => return sqrtq(x),
489 else => @compileError("unreachable"),
499 64 => return sqrt_f64(x),
500 80 => return sqrt_f80(x),
501 128 => return sqrt_f128(x),
502 else => comptime unreachable,
490503 }
491504}
492505
......@@ -545,187 +558,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 {
545558 return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40);
546559}
547560
548test "__sqrth" {
561test "sqrt_f16" {
549562 // sqrt(±0) is ±0
550 try std.testing.expectEqual(__sqrth(0x0.0p0), 0x0.0p0);
551 try std.testing.expectEqual(__sqrth(-0x0.0p0), -0x0.0p0);
563 try std.testing.expectEqual(sqrt_f16(0x0.0p0), 0x0.0p0);
564 try std.testing.expectEqual(sqrt_f16(-0x0.0p0), -0x0.0p0);
552565 // sqrt(+max) is finite
553 try std.testing.expectEqual(__sqrth(0x1.FFCp15), 0x1.FFCp7);
566 try std.testing.expectEqual(sqrt_f16(0x1.FFCp15), 0x1.FFCp7);
554567 // sqrt(4)=2
555 try std.testing.expectEqual(__sqrth(0x1p2), 0x1p1);
568 try std.testing.expectEqual(sqrt_f16(0x1p2), 0x1p1);
556569 // sqrt(x) for x=1, 1±ulp
557 try std.testing.expectEqual(__sqrth(0x1p0), 0x1p0);
558 try std.testing.expectEqual(__sqrth(0x1.004p0), 0x1p0);
559 try std.testing.expectEqual(__sqrth(0x1.FF8p-1), 0x1.FFCp-1);
570 try std.testing.expectEqual(sqrt_f16(0x1p0), 0x1p0);
571 try std.testing.expectEqual(sqrt_f16(0x1.004p0), 0x1p0);
572 try std.testing.expectEqual(sqrt_f16(0x1.FF8p-1), 0x1.FFCp-1);
560573 // sqrt(+min) is non-zero
561 try std.testing.expectEqual(__sqrth(0x1p-14), 0x1p-7);
574 try std.testing.expectEqual(sqrt_f16(0x1p-14), 0x1p-7);
562575 // sqrt(min subnormal) is non-zero
563 try std.testing.expectEqual(__sqrth(0x0.004p-14), 0x1p-12);
576 try std.testing.expectEqual(sqrt_f16(0x0.004p-14), 0x1p-12);
564577 // sqrt(inf) is inf
565 try std.testing.expect(math.isInf(__sqrth(math.inf(f16))));
578 try std.testing.expect(math.isInf(sqrt_f16(math.inf(f16))));
566579 // sqrt(nan) is nan
567 try std.testing.expect(math.isNan(__sqrth(math.nan(f16))));
580 try std.testing.expect(math.isNan(sqrt_f16(math.nan(f16))));
568581 // sqrt(-ve) is nan
569 try std.testing.expect(math.isNan(__sqrth(-0x1p-14)));
570 try std.testing.expect(math.isNan(__sqrth(-0x1p+0)));
571 try std.testing.expect(math.isNan(__sqrth(-math.inf(f16))));
582 try std.testing.expect(math.isNan(sqrt_f16(-0x1p-14)));
583 try std.testing.expect(math.isNan(sqrt_f16(-0x1p+0)));
584 try std.testing.expect(math.isNan(sqrt_f16(-math.inf(f16))));
572585 // random arguments
573 try std.testing.expectEqual(__sqrth(0x1.1p14), 0x1.08p7);
574 try std.testing.expectEqual(__sqrth(0x1.C9p-12), 0x1.56p-6);
575 try std.testing.expectEqual(__sqrth(0x1.CE8p-7), 0x1.E68p-4);
576 try std.testing.expectEqual(__sqrth(0x1.134p-7), 0x1.778p-4);
577 try std.testing.expectEqual(__sqrth(0x1.E9Cp-10), 0x1.62p-5);
578 try std.testing.expectEqual(__sqrth(0x1.3Dp9), 0x1.92Cp4);
579 try std.testing.expectEqual(__sqrth(0x1.AA4p8), 0x1.4A4p4);
580 try std.testing.expectEqual(__sqrth(0x1.8A8p4), 0x1.3DCp2);
581 try std.testing.expectEqual(__sqrth(0x1.8Fp-7), 0x1.C4p-4);
582 try std.testing.expectEqual(__sqrth(0x1.584p-11), 0x1.A3Cp-6);
586 try std.testing.expectEqual(sqrt_f16(0x1.1p14), 0x1.08p7);
587 try std.testing.expectEqual(sqrt_f16(0x1.C9p-12), 0x1.56p-6);
588 try std.testing.expectEqual(sqrt_f16(0x1.CE8p-7), 0x1.E68p-4);
589 try std.testing.expectEqual(sqrt_f16(0x1.134p-7), 0x1.778p-4);
590 try std.testing.expectEqual(sqrt_f16(0x1.E9Cp-10), 0x1.62p-5);
591 try std.testing.expectEqual(sqrt_f16(0x1.3Dp9), 0x1.92Cp4);
592 try std.testing.expectEqual(sqrt_f16(0x1.AA4p8), 0x1.4A4p4);
593 try std.testing.expectEqual(sqrt_f16(0x1.8A8p4), 0x1.3DCp2);
594 try std.testing.expectEqual(sqrt_f16(0x1.8Fp-7), 0x1.C4p-4);
595 try std.testing.expectEqual(sqrt_f16(0x1.584p-11), 0x1.A3Cp-6);
583596}
584597
585test "sqrtf" {
598test "sqrt_f32" {
586599 // sqrt(±0) is ±0
587 try std.testing.expectEqual(sqrtf(0x0.0p0), 0x0.0p0);
588 try std.testing.expectEqual(sqrtf(-0x0.0p0), -0x0.0p0);
600 try std.testing.expectEqual(sqrt_f32(0x0.0p0), 0x0.0p0);
601 try std.testing.expectEqual(sqrt_f32(-0x0.0p0), -0x0.0p0);
589602 // sqrt(+max) is finite
590 try std.testing.expectEqual(sqrtf(0x1.FFFFFEp127), 0x1.FFFFFEp63);
603 try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp127), 0x1.FFFFFEp63);
591604 // sqrt(4)=2
592 try std.testing.expectEqual(sqrtf(0x1p2), 0x1p1);
605 try std.testing.expectEqual(sqrt_f32(0x1p2), 0x1p1);
593606 // sqrt(x) for x=1, 1±ulp
594 try std.testing.expectEqual(sqrtf(0x1p0), 0x1p0);
595 try std.testing.expectEqual(sqrtf(0x1.000002p0), 0x1p0);
596 try std.testing.expectEqual(sqrtf(0x1.FFFFFEp-1), 0x1.FFFFFEp-1);
607 try std.testing.expectEqual(sqrt_f32(0x1p0), 0x1p0);
608 try std.testing.expectEqual(sqrt_f32(0x1.000002p0), 0x1p0);
609 try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp-1), 0x1.FFFFFEp-1);
597610 // sqrt(+min) is non-zero
598 try std.testing.expectEqual(sqrtf(0x1p-126), 0x1p-63);
611 try std.testing.expectEqual(sqrt_f32(0x1p-126), 0x1p-63);
599612 // sqrt(min subnormal) is non-zero
600 try std.testing.expectEqual(sqrtf(0x0.000002p-126), 0x1.6a09e6p-75);
613 try std.testing.expectEqual(sqrt_f32(0x0.000002p-126), 0x1.6a09e6p-75);
601614 // sqrt(inf) is inf
602 try std.testing.expect(math.isInf(sqrtf(math.inf(f32))));
615 try std.testing.expect(math.isInf(sqrt_f32(math.inf(f32))));
603616 // sqrt(nan) is nan
604 try std.testing.expect(math.isNan(sqrtf(math.nan(f32))));
617 try std.testing.expect(math.isNan(sqrt_f32(math.nan(f32))));
605618 // sqrt(-ve) is nan
606 try std.testing.expect(math.isNan(sqrtf(-0x1p-149)));
607 try std.testing.expect(math.isNan(sqrtf(-0x1p0)));
608 try std.testing.expect(math.isNan(sqrtf(-math.inf(f32))));
619 try std.testing.expect(math.isNan(sqrt_f32(-0x1p-149)));
620 try std.testing.expect(math.isNan(sqrt_f32(-0x1p0)));
621 try std.testing.expect(math.isNan(sqrt_f32(-math.inf(f32))));
609622 // random arguments
610 try std.testing.expectEqual(sqrtf(0x1.4DD57Ep77), 0x1.9D6DA8p38);
611 try std.testing.expectEqual(sqrtf(0x1.871848p102), 0x1.3C6AFAp51);
612 try std.testing.expectEqual(sqrtf(0x1.A1D748p-112), 0x1.470EFCp-56);
613 try std.testing.expectEqual(sqrtf(0x1.E626C2p18), 0x1.60C80Ep9);
614 try std.testing.expectEqual(sqrtf(0x1.E80E66p-29), 0x1.F3E282p-15);
615 try std.testing.expectEqual(sqrtf(0x1.B47204p89), 0x1.D8B732p44);
616 try std.testing.expectEqual(sqrtf(0x1.77F45p15), 0x1.B6BC3Ap7);
617 try std.testing.expectEqual(sqrtf(0x1.AD5F5p-48), 0x1.4B8A72p-24);
618 try std.testing.expectEqual(sqrtf(0x1.91A39p-76), 0x1.40A7A8p-38);
619 try std.testing.expectEqual(sqrtf(0x1.DAE088p79), 0x1.ED16DCp39);
623 try std.testing.expectEqual(sqrt_f32(0x1.4DD57Ep77), 0x1.9D6DA8p38);
624 try std.testing.expectEqual(sqrt_f32(0x1.871848p102), 0x1.3C6AFAp51);
625 try std.testing.expectEqual(sqrt_f32(0x1.A1D748p-112), 0x1.470EFCp-56);
626 try std.testing.expectEqual(sqrt_f32(0x1.E626C2p18), 0x1.60C80Ep9);
627 try std.testing.expectEqual(sqrt_f32(0x1.E80E66p-29), 0x1.F3E282p-15);
628 try std.testing.expectEqual(sqrt_f32(0x1.B47204p89), 0x1.D8B732p44);
629 try std.testing.expectEqual(sqrt_f32(0x1.77F45p15), 0x1.B6BC3Ap7);
630 try std.testing.expectEqual(sqrt_f32(0x1.AD5F5p-48), 0x1.4B8A72p-24);
631 try std.testing.expectEqual(sqrt_f32(0x1.91A39p-76), 0x1.40A7A8p-38);
632 try std.testing.expectEqual(sqrt_f32(0x1.DAE088p79), 0x1.ED16DCp39);
620633}
621634
622test "sqrt" {
635test "sqrt_f64" {
623636 // sqrt(±0) is ±0
624 try std.testing.expectEqual(sqrt(0x0.0p0), 0x0.0p0);
625 try std.testing.expectEqual(sqrt(-0x0.0p0), -0x0.0p0);
637 try std.testing.expectEqual(sqrt_f64(0x0.0p0), 0x0.0p0);
638 try std.testing.expectEqual(sqrt_f64(-0x0.0p0), -0x0.0p0);
626639 // sqrt(+max) is finite
627 try std.testing.expectEqual(sqrt(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511);
640 try std.testing.expectEqual(sqrt_f64(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511);
628641 // sqrt(4)=2
629 try std.testing.expectEqual(sqrt(0x1p2), 0x1p1);
642 try std.testing.expectEqual(sqrt_f64(0x1p2), 0x1p1);
630643 // sqrt(x) for x=1, 1±ulp
631 try std.testing.expectEqual(sqrt(0x1p0), 0x1p0);
632 try std.testing.expectEqual(sqrt(0x1p0 + math.floatEps(f64)), 0x1p0);
633 try std.testing.expectEqual(sqrt(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1);
644 try std.testing.expectEqual(sqrt_f64(0x1p0), 0x1p0);
645 try std.testing.expectEqual(sqrt_f64(0x1p0 + math.floatEps(f64)), 0x1p0);
646 try std.testing.expectEqual(sqrt_f64(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1);
634647 // sqrt(+min) is non-zero
635 try std.testing.expectEqual(sqrt(math.floatMin(f64)), 0x1p-511);
648 try std.testing.expectEqual(sqrt_f64(math.floatMin(f64)), 0x1p-511);
636649 // sqrt(min subnormal) is non-zero
637 try std.testing.expectEqual(sqrt(math.floatTrueMin(f64)), 0x1p-537);
650 try std.testing.expectEqual(sqrt_f64(math.floatTrueMin(f64)), 0x1p-537);
638651 // sqrt(inf) is inf
639 try std.testing.expect(math.isInf(sqrt(math.inf(f64))));
652 try std.testing.expect(math.isInf(sqrt_f64(math.inf(f64))));
640653 // sqrt(nan) is nan
641 try std.testing.expect(math.isNan(sqrt(math.nan(f64))));
654 try std.testing.expect(math.isNan(sqrt_f64(math.nan(f64))));
642655 // sqrt(-ve) is nan
643 try std.testing.expect(math.isNan(sqrt(-0x1p-1074)));
644 try std.testing.expect(math.isNan(sqrt(-0x1p0)));
645 try std.testing.expect(math.isNan(sqrt(-math.inf(f64))));
656 try std.testing.expect(math.isNan(sqrt_f64(-0x1p-1074)));
657 try std.testing.expect(math.isNan(sqrt_f64(-0x1p0)));
658 try std.testing.expect(math.isNan(sqrt_f64(-math.inf(f64))));
646659 // random arguments
647 try std.testing.expectEqual(sqrt(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235);
648 try std.testing.expectEqual(sqrt(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395);
649 try std.testing.expectEqual(sqrt(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69);
650 try std.testing.expectEqual(sqrt(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139);
651 try std.testing.expectEqual(sqrt(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458);
652 try std.testing.expectEqual(sqrt(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125);
653 try std.testing.expectEqual(sqrt(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243);
654 try std.testing.expectEqual(sqrt(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169);
655 try std.testing.expectEqual(sqrt(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133);
656 try std.testing.expectEqual(sqrt(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178);
660 try std.testing.expectEqual(sqrt_f64(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235);
661 try std.testing.expectEqual(sqrt_f64(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395);
662 try std.testing.expectEqual(sqrt_f64(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69);
663 try std.testing.expectEqual(sqrt_f64(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139);
664 try std.testing.expectEqual(sqrt_f64(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458);
665 try std.testing.expectEqual(sqrt_f64(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125);
666 try std.testing.expectEqual(sqrt_f64(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243);
667 try std.testing.expectEqual(sqrt_f64(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169);
668 try std.testing.expectEqual(sqrt_f64(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133);
669 try std.testing.expectEqual(sqrt_f64(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178);
657670}
658671
659672test "__sqrtx" {
660673 // sqrt(±0) is ±0
661 try std.testing.expectEqual(__sqrtx(0x0.0p0), 0x0.0p0);
662 try std.testing.expectEqual(__sqrtx(-0x0.0p0), -0x0.0p0);
674 try std.testing.expectEqual(sqrt_f80(0x0.0p0), 0x0.0p0);
675 try std.testing.expectEqual(sqrt_f80(-0x0.0p0), -0x0.0p0);
663676 // sqrt(+max) is finite
664 try std.testing.expectEqual(__sqrtx(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191);
677 try std.testing.expectEqual(sqrt_f80(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191);
665678 // sqrt(4)=2
666 try std.testing.expectEqual(__sqrtx(0x1p2), 0x1p1);
679 try std.testing.expectEqual(sqrt_f80(0x1p2), 0x1p1);
667680 // sqrt(x) for x=1, 1±ulp
668 try std.testing.expectEqual(__sqrtx(0x1p0), 0x1p0);
669 try std.testing.expectEqual(__sqrtx(0x1p0 + math.floatEps(f80)), 0x1p0);
670 try std.testing.expectEqual(__sqrtx(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1);
681 try std.testing.expectEqual(sqrt_f80(0x1p0), 0x1p0);
682 try std.testing.expectEqual(sqrt_f80(0x1p0 + math.floatEps(f80)), 0x1p0);
683 try std.testing.expectEqual(sqrt_f80(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1);
671684 // sqrt(+min) is non-zero
672 try std.testing.expectEqual(__sqrtx(math.floatMin(f80)), 0x1p-8191);
685 try std.testing.expectEqual(sqrt_f80(math.floatMin(f80)), 0x1p-8191);
673686 // sqrt(min subnormal) is non-zero
674 try std.testing.expectEqual(__sqrtx(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223);
687 try std.testing.expectEqual(sqrt_f80(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223);
675688 // sqrt(inf) is inf
676 try std.testing.expect(math.isInf(__sqrtx(math.inf(f80))));
689 try std.testing.expect(math.isInf(sqrt_f80(math.inf(f80))));
677690 // sqrt(nan) is nan
678 try std.testing.expect(math.isNan(__sqrtx(math.nan(f80))));
691 try std.testing.expect(math.isNan(sqrt_f80(math.nan(f80))));
679692 // sqrt(-ve) is nan
680 try std.testing.expect(math.isNan(__sqrtx(-0x1p-16442)));
681 try std.testing.expect(math.isNan(__sqrtx(-0x1p0)));
682 try std.testing.expect(math.isNan(__sqrtx(-math.inf(f80))));
693 try std.testing.expect(math.isNan(sqrt_f80(-0x1p-16442)));
694 try std.testing.expect(math.isNan(sqrt_f80(-0x1p0)));
695 try std.testing.expect(math.isNan(sqrt_f80(-math.inf(f80))));
683696 // random arguments
684 try std.testing.expectEqual(__sqrtx(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741);
685 try std.testing.expectEqual(__sqrtx(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165);
686 try std.testing.expectEqual(__sqrtx(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856);
687 try std.testing.expectEqual(__sqrtx(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432);
688 try std.testing.expectEqual(__sqrtx(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591);
689 try std.testing.expectEqual(__sqrtx(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315);
690 try std.testing.expectEqual(__sqrtx(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517);
691 try std.testing.expectEqual(__sqrtx(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706);
692 try std.testing.expectEqual(__sqrtx(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760);
693 try std.testing.expectEqual(__sqrtx(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685);
697 try std.testing.expectEqual(sqrt_f80(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741);
698 try std.testing.expectEqual(sqrt_f80(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165);
699 try std.testing.expectEqual(sqrt_f80(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856);
700 try std.testing.expectEqual(sqrt_f80(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432);
701 try std.testing.expectEqual(sqrt_f80(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591);
702 try std.testing.expectEqual(sqrt_f80(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315);
703 try std.testing.expectEqual(sqrt_f80(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517);
704 try std.testing.expectEqual(sqrt_f80(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706);
705 try std.testing.expectEqual(sqrt_f80(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760);
706 try std.testing.expectEqual(sqrt_f80(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685);
694707}
695708
696test "sqrtq" {
709test "sqrt_f128" {
697710 // sqrt(±0) is ±0
698 try std.testing.expectEqual(sqrtq(0x0.0p0), 0x0.0p0);
699 try std.testing.expectEqual(sqrtq(-0x0.0p0), -0x0.0p0);
711 try std.testing.expectEqual(sqrt_f128(0x0.0p0), 0x0.0p0);
712 try std.testing.expectEqual(sqrt_f128(-0x0.0p0), -0x0.0p0);
700713 // sqrt(+max) is finite
701 try std.testing.expectEqual(sqrtq(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191);
714 try std.testing.expectEqual(sqrt_f128(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191);
702715 // sqrt(4)=2
703 try std.testing.expectEqual(sqrtq(0x1p2), 0x1p1);
716 try std.testing.expectEqual(sqrt_f128(0x1p2), 0x1p1);
704717 // sqrt(x) for x=1, 1±ulp
705 try std.testing.expectEqual(sqrtq(0x1p0), 0x1p0);
706 try std.testing.expectEqual(sqrtq(0x1p0 + math.floatEps(f128)), 0x1p0);
707 try std.testing.expectEqual(sqrtq(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1);
718 try std.testing.expectEqual(sqrt_f128(0x1p0), 0x1p0);
719 try std.testing.expectEqual(sqrt_f128(0x1p0 + math.floatEps(f128)), 0x1p0);
720 try std.testing.expectEqual(sqrt_f128(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1);
708721 // sqrt(+min) is non-zero
709 try std.testing.expectEqual(sqrtq(math.floatMin(f128)), 0x1p-8191);
722 try std.testing.expectEqual(sqrt_f128(math.floatMin(f128)), 0x1p-8191);
710723 // sqrt(min subnormal) is non-zero
711 try std.testing.expectEqual(sqrtq(math.floatTrueMin(f128)), 0x1p-8247);
724 try std.testing.expectEqual(sqrt_f128(math.floatTrueMin(f128)), 0x1p-8247);
712725 // sqrt(inf) is inf
713 try std.testing.expect(math.isInf(sqrtq(math.inf(f128))));
726 try std.testing.expect(math.isInf(sqrt_f128(math.inf(f128))));
714727 // sqrt(nan) is nan
715 try std.testing.expect(math.isNan(sqrtq(math.nan(f128))));
728 try std.testing.expect(math.isNan(sqrt_f128(math.nan(f128))));
716729 // sqrt(-ve) is nan
717 try std.testing.expect(math.isNan(sqrtq(-0x1p-16442)));
718 try std.testing.expect(math.isNan(sqrtq(-0x1p0)));
719 try std.testing.expect(math.isNan(sqrtq(-math.inf(f128))));
730 try std.testing.expect(math.isNan(sqrt_f128(-0x1p-16442)));
731 try std.testing.expect(math.isNan(sqrt_f128(-0x1p0)));
732 try std.testing.expect(math.isNan(sqrt_f128(-math.inf(f128))));
720733 // random arguments
721 try std.testing.expectEqual(sqrtq(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681);
722 try std.testing.expectEqual(sqrtq(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882);
723 try std.testing.expectEqual(sqrtq(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812);
724 try std.testing.expectEqual(sqrtq(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031);
725 try std.testing.expectEqual(sqrtq(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513);
726 try std.testing.expectEqual(sqrtq(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917);
727 try std.testing.expectEqual(sqrtq(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256);
728 try std.testing.expectEqual(sqrtq(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476);
729 try std.testing.expectEqual(sqrtq(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446);
730 try std.testing.expectEqual(sqrtq(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976);
734 try std.testing.expectEqual(sqrt_f128(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681);
735 try std.testing.expectEqual(sqrt_f128(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882);
736 try std.testing.expectEqual(sqrt_f128(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812);
737 try std.testing.expectEqual(sqrt_f128(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031);
738 try std.testing.expectEqual(sqrt_f128(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513);
739 try std.testing.expectEqual(sqrt_f128(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917);
740 try std.testing.expectEqual(sqrt_f128(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256);
741 try std.testing.expectEqual(sqrt_f128(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476);
742 try std.testing.expectEqual(sqrt_f128(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446);
743 try std.testing.expectEqual(sqrt_f128(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976);
731744}
lib/compiler_rt/subdf3.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const addf3 = @import("./addf3.zig").addf3;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dsub, "__aeabi_dsub");
8 } else {
9 symbol(&__subdf3, "__subdf3");
10 }
11}
12
13fn __subdf3(a: f64, b: f64) callconv(.c) f64 {
14 return sub(a, b);
15}
16
17fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 {
18 return sub(a, b);
19}
20
21inline fn sub(a: f64, b: f64) f64 {
22 const neg_b = @as(f64, @bitCast(@as(u64, @bitCast(b)) ^ (@as(u64, 1) << 63)));
23 return addf3(f64, a, neg_b);
24}
lib/compiler_rt/subhf3.zig deleted-12
......@@ -1,12 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 symbol(&__subhf3, "__subhf3");
7}
8
9fn __subhf3(a: f16, b: f16) callconv(.c) f16 {
10 const neg_b = @as(f16, @bitCast(@as(u16, @bitCast(b)) ^ (@as(u16, 1) << 15)));
11 return addf3(f16, a, neg_b);
12}
lib/compiler_rt/subsf3.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_fsub, "__aeabi_fsub");
8 } else {
9 symbol(&__subsf3, "__subsf3");
10 }
11}
12
13fn __subsf3(a: f32, b: f32) callconv(.c) f32 {
14 return sub(a, b);
15}
16
17fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return sub(a, b);
19}
20
21inline fn sub(a: f32, b: f32) f32 {
22 const neg_b = @as(f32, @bitCast(@as(u32, @bitCast(b)) ^ (@as(u32, 1) << 31)));
23 return addf3(f32, a, neg_b);
24}
lib/compiler_rt/subtf3.zig deleted-27
......@@ -1,27 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const addf3 = @import("./addf3.zig").addf3;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__subtf3, "__subkf3");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_sub, "_Qp_sub");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__subtf3, "_Q_sub");
12 }
13 symbol(&__subtf3, "__subtf3");
14}
15
16pub fn __subtf3(a: f128, b: f128) callconv(.c) f128 {
17 return sub(a, b);
18}
19
20fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void {
21 c.* = sub(a.*, b.*);
22}
23
24inline fn sub(a: f128, b: f128) f128 {
25 const neg_b = @as(f128, @bitCast(@as(u128, @bitCast(b)) ^ (@as(u128, 1) << 127)));
26 return addf3(f128, a, neg_b);
27}
lib/compiler_rt/subvdi3.zig+3-2
......@@ -1,5 +1,6 @@
1const symbol = @import("../compiler_rt.zig").symbol;
21const testing = @import("std").testing;
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
34
45comptime {
56 symbol(&__subvdi3, "__subvdi3");
......@@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
910 const sum = a -% b;
1011 // Overflow occurred iff the operands have opposite signs, and the sign of the
1112 // sum is the opposite of the lhs sign.
12 if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
13 if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow");
1314 return sum;
1415}
1516
lib/compiler_rt/subvsi3.zig+1-1
......@@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
1010 const sum = a -% b;
1111 // Overflow occurred iff the operands have opposite signs, and the sign of the
1212 // sum is the opposite of the lhs sign.
13 if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
13 if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow");
1414 return sum;
1515}
1616
lib/compiler_rt/subxf3.zig deleted-13
......@@ -1,13 +0,0 @@
1const std = @import("std");
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 symbol(&__subxf3, "__subxf3");
6}
7
8fn __subxf3(a: f80, b: f80) callconv(.c) f80 {
9 var b_rep = std.math.F80.fromFloat(b);
10 b_rep.exp ^= 0x8000;
11 const neg_b = b_rep.toFloat();
12 return a + neg_b;
13}
lib/compiler_rt/tan.zig+53-37
......@@ -21,26 +21,29 @@ const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l;
2121
2222const arch = builtin.cpu.arch;
2323const compiler_rt = @import("../compiler_rt.zig");
24const symbol = @import("../compiler_rt.zig").symbol;
24const symbol = compiler_rt.symbol;
2525
2626comptime {
27 symbol(&tanh, "__tanh");
27 symbol(&__tanh, "__tanh");
2828 symbol(&tanf, "tanf");
2929 symbol(&tan, "tan");
30 symbol(&tanx, "__tanx");
31 if (compiler_rt.want_ppc_abi) {
32 symbol(&tanq, "tanf128");
33 }
34 symbol(&tanq, "tanq");
30 symbol(&__tanx, "__tanx");
31 symbol(&tanq, "tanf128");
3532 symbol(&tanl, "tanl");
3633}
3734
38pub fn tanh(x: f16) callconv(.c) f16 {
35fn __tanh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
36 return compiler_rt.f16.toAbi(tan_f16(compiler_rt.f16.fromAbi(x)));
37}
38pub fn tan_f16(x: f16) f16 {
3939 // TODO: more efficient implementation
40 return @floatCast(tanf(x));
40 return @floatCast(tan_f32(x));
4141}
4242
43pub fn tanf(x: f32) callconv(.c) f32 {
43fn tanf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
44 return compiler_rt.f32.toAbi(tan_f32(compiler_rt.f32.fromAbi(x)));
45}
46pub fn tan_f32(x: f32) f32 {
4447 // Small multiples of pi/2 rounded to double precision.
4548 const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
4649 const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
......@@ -90,7 +93,10 @@ pub fn tanf(x: f32) callconv(.c) f32 {
9093 return kernel.tandf(y, n & 1 != 0);
9194}
9295
93pub fn tan(x: f64) callconv(.c) f64 {
96fn tan(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
97 return compiler_rt.f64.toAbi(tan_f64(compiler_rt.f64.fromAbi(x)));
98}
99pub fn tan_f64(x: f64) f64 {
94100 var ix = @as(u64, @bitCast(x)) >> 32;
95101 ix &= 0x7fffffff;
96102
......@@ -120,7 +126,10 @@ pub fn tan(x: f64) callconv(.c) f64 {
120126 return kernel.tan(y[0], y[1], n & 1 != 0);
121127}
122128
123pub fn tanx(x: f80) callconv(.c) f80 {
129fn __tanx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
130 return compiler_rt.f80.toAbi(tan_f80(compiler_rt.f80.fromAbi(x)));
131}
132pub fn tan_f80(x: f80) f80 {
124133 const se = ld.signExponent(x) & 0x7fff;
125134 if (se == 0x7fff) {
126135 return x - x;
......@@ -141,7 +150,10 @@ pub fn tanx(x: f80) callconv(.c) f80 {
141150 return kernel.tanx(y[0], y[1], n & 1);
142151}
143152
144pub fn tanq(x: f128) callconv(.c) f128 {
153fn tanq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
154 return compiler_rt.f128.toAbi(tan_f128(compiler_rt.f128.fromAbi(x)));
155}
156pub fn tan_f128(x: f128) f128 {
145157 const se = ld.signExponent(x) & 0x7fff;
146158 if (se == 0x7fff) {
147159 return x - x;
......@@ -164,18 +176,21 @@ pub fn tanq(x: f128) callconv(.c) f128 {
164176
165177pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble {
166178 switch (@typeInfo(c_longdouble).float.bits) {
167 64 => return tan(x),
168 80 => return tanx(x),
169 128 => return tanq(x),
170 else => @compileError("unreachable"),
179 64 => return tan_f64(x),
180 80 => return tan_f80(x),
181 128 => return tan_f128(x),
182 else => comptime unreachable,
171183 }
172184}
173185
174186fn testTanNormal(comptime T: type) !void {
175187 const f = switch (T) {
176 f32 => tanf,
177 f64 => tan,
178 else => @compileError("unimplemented"),
188 f16 => tan_f16,
189 f32 => tan_f32,
190 f64 => tan_f64,
191 f80 => tan_f80,
192 f128 => tan_f128,
193 else => comptime unreachable,
179194 };
180195 const epsilon = 0.00001;
181196
......@@ -189,11 +204,12 @@ fn testTanNormal(comptime T: type) !void {
189204
190205fn testTanSpecial(comptime T: type) !void {
191206 const f = switch (T) {
192 f32 => tanf,
193 f64 => tan,
194 f80 => tanx,
195 f128 => tanq,
196 else => @compileError("unimplemented"),
207 f16 => tan_f16,
208 f32 => tan_f32,
209 f64 => tan_f64,
210 f80 => tan_f80,
211 f128 => tan_f128,
212 else => comptime unreachable,
197213 };
198214
199215 try expect(math.isPositiveZero(f(0.0)));
......@@ -214,23 +230,23 @@ test "tan64.normal" {
214230test "tan80.normal" {
215231 const epsilon = math.floatEps(f80);
216232
217 try expectApproxEqAbs(@as(f80, 0.0), tanx(0.0), epsilon);
218 try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tanx(0.2), epsilon);
219 try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tanx(0.8923), epsilon);
220 try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tanx(1.5), epsilon);
221 try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tanx(37.45), epsilon);
222 try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tanx(89.123), epsilon);
233 try expectApproxEqAbs(@as(f80, 0.0), tan_f80(0.0), epsilon);
234 try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tan_f80(0.2), epsilon);
235 try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tan_f80(0.8923), epsilon);
236 try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tan_f80(1.5), epsilon);
237 try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tan_f80(37.45), epsilon);
238 try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tan_f80(89.123), epsilon);
223239}
224240
225241test "tan128.normal" {
226242 const epsilon = math.floatEps(f128);
227243
228 try expectApproxEqAbs(@as(f128, 0.0), tanq(0.0), epsilon);
229 try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tanq(0.2), epsilon);
230 try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tanq(0.8923), epsilon);
231 try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tanq(1.5), epsilon);
232 try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tanq(37.45), epsilon);
233 try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tanq(89.123), epsilon);
244 try expectApproxEqAbs(@as(f128, 0.0), tan_f128(0.0), epsilon);
245 try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tan_f128(0.2), epsilon);
246 try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tan_f128(0.8923), epsilon);
247 try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tan_f128(1.5), epsilon);
248 try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tan_f128(37.45), epsilon);
249 try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tan_f128(89.123), epsilon);
234250}
235251
236252test "tan32.special" {
lib/compiler_rt/trunc.zig+77-47
......@@ -17,19 +17,22 @@ comptime {
1717 symbol(&truncf, "truncf");
1818 symbol(&trunc, "trunc");
1919 symbol(&__truncx, "__truncx");
20 if (compiler_rt.want_ppc_abi) {
21 symbol(&truncq, "truncf128");
22 }
23 symbol(&truncq, "truncq");
20 symbol(&truncq, "truncf128");
2421 symbol(&truncl, "truncl");
2522}
2623
27pub fn __trunch(x: f16) callconv(.c) f16 {
24fn __trunch(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi {
25 return compiler_rt.f16.toAbi(trunc_f16(compiler_rt.f16.fromAbi(x)));
26}
27pub fn trunc_f16(x: f16) f16 {
2828 // TODO: more efficient implementation
29 return @floatCast(truncf(x));
29 return @floatCast(trunc_f32(x));
3030}
3131
32pub fn truncf(x: f32) callconv(.c) f32 {
32fn truncf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi {
33 return compiler_rt.f32.toAbi(trunc_f32(compiler_rt.f32.fromAbi(x)));
34}
35pub fn trunc_f32(x: f32) f32 {
3336 const u: u32 = @bitCast(x);
3437 var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9;
3538 var m: u32 = undefined;
......@@ -50,7 +53,10 @@ pub fn truncf(x: f32) callconv(.c) f32 {
5053 }
5154}
5255
53pub fn trunc(x: f64) callconv(.c) f64 {
56fn trunc(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi {
57 return compiler_rt.f64.toAbi(trunc_f64(compiler_rt.f64.fromAbi(x)));
58}
59pub fn trunc_f64(x: f64) f64 {
5460 const u: u64 = @bitCast(x);
5561 var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12;
5662 var m: u64 = undefined;
......@@ -71,12 +77,18 @@ pub fn trunc(x: f64) callconv(.c) f64 {
7177 }
7278}
7379
74pub fn __truncx(x: f80) callconv(.c) f80 {
80fn __truncx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi {
81 return compiler_rt.f80.toAbi(trunc_f80(compiler_rt.f80.fromAbi(x)));
82}
83pub fn trunc_f80(x: f80) f80 {
7584 // TODO: more efficient implementation
76 return @floatCast(truncq(x));
85 return @floatCast(trunc_f128(x));
7786}
7887
79pub fn truncq(x: f128) callconv(.c) f128 {
88fn truncq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi {
89 return compiler_rt.f128.toAbi(trunc_f128(compiler_rt.f128.fromAbi(x)));
90}
91pub fn trunc_f128(x: f128) f128 {
8092 const u: u128 = @bitCast(x);
8193 var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16;
8294 var m: u128 = undefined;
......@@ -99,51 +111,69 @@ pub fn truncq(x: f128) callconv(.c) f128 {
99111
100112pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble {
101113 switch (@typeInfo(c_longdouble).float.bits) {
102 64 => return trunc(x),
103 80 => return __truncx(x),
104 128 => return truncq(x),
105 else => @compileError("unreachable"),
114 64 => return trunc_f64(x),
115 80 => return trunc_f80(x),
116 128 => return trunc_f128(x),
117 else => comptime unreachable,
106118 }
107119}
108120
109test "trunc32" {
110 try expect(truncf(1.3) == 1.0);
111 try expect(truncf(-1.3) == -1.0);
112 try expect(truncf(0.2) == 0.0);
113}
114
115test "trunc64" {
116 try expect(trunc(1.3) == 1.0);
117 try expect(trunc(-1.3) == -1.0);
118 try expect(trunc(0.2) == 0.0);
121test trunc_f16 {
122 try expect(trunc_f16(1.3) == 1.0);
123 try expect(trunc_f16(-1.3) == -1.0);
124 try expect(math.isPositiveZero(trunc_f16(0.2)));
125 try expect(math.isNegativeZero(trunc_f16(-0.2)));
126 try expect(math.isPositiveZero(trunc_f16(0.0)));
127 try expect(math.isNegativeZero(trunc_f16(-0.0)));
128 try expect(math.isPositiveInf(trunc_f16(math.inf(f32))));
129 try expect(math.isNegativeInf(trunc_f16(-math.inf(f32))));
130 try expect(math.isNan(trunc_f16(math.nan(f32))));
119131}
120132
121test "trunc128" {
122 try expect(truncq(1.3) == 1.0);
123 try expect(truncq(-1.3) == -1.0);
124 try expect(truncq(0.2) == 0.0);
133test trunc_f32 {
134 try expect(trunc_f32(1.3) == 1.0);
135 try expect(trunc_f32(-1.3) == -1.0);
136 try expect(math.isPositiveZero(trunc_f32(0.2)));
137 try expect(math.isNegativeZero(trunc_f32(-0.2)));
138 try expect(math.isPositiveZero(trunc_f32(0.0)));
139 try expect(math.isNegativeZero(trunc_f32(-0.0)));
140 try expect(math.isPositiveInf(trunc_f32(math.inf(f32))));
141 try expect(math.isNegativeInf(trunc_f32(-math.inf(f32))));
142 try expect(math.isNan(trunc_f32(math.nan(f32))));
125143}
126144
127test "trunc32.special" {
128 try expect(truncf(0.0) == 0.0); // 0x3F800000
129 try expect(truncf(-0.0) == -0.0);
130 try expect(math.isPositiveInf(truncf(math.inf(f32))));
131 try expect(math.isNegativeInf(truncf(-math.inf(f32))));
132 try expect(math.isNan(truncf(math.nan(f32))));
145test trunc_f64 {
146 try expect(trunc_f64(1.3) == 1.0);
147 try expect(trunc_f64(-1.3) == -1.0);
148 try expect(math.isPositiveZero(trunc_f64(0.2)));
149 try expect(math.isNegativeZero(trunc_f64(-0.2)));
150 try expect(math.isPositiveZero(trunc_f64(0.0)));
151 try expect(math.isNegativeZero(trunc_f64(-0.0)));
152 try expect(math.isPositiveInf(trunc_f64(math.inf(f64))));
153 try expect(math.isNegativeInf(trunc_f64(-math.inf(f64))));
154 try expect(math.isNan(trunc_f64(math.nan(f64))));
133155}
134156
135test "trunc64.special" {
136 try expect(trunc(0.0) == 0.0);
137 try expect(trunc(-0.0) == -0.0);
138 try expect(math.isPositiveInf(trunc(math.inf(f64))));
139 try expect(math.isNegativeInf(trunc(-math.inf(f64))));
140 try expect(math.isNan(trunc(math.nan(f64))));
157test trunc_f80 {
158 try expect(trunc_f80(1.3) == 1.0);
159 try expect(trunc_f80(-1.3) == -1.0);
160 try expect(math.isPositiveZero(trunc_f80(0.2)));
161 try expect(math.isNegativeZero(trunc_f80(-0.2)));
162 try expect(math.isPositiveZero(trunc_f80(0.0)));
163 try expect(math.isNegativeZero(trunc_f80(-0.0)));
164 try expect(math.isPositiveInf(trunc_f80(math.inf(f64))));
165 try expect(math.isNegativeInf(trunc_f80(-math.inf(f64))));
166 try expect(math.isNan(trunc_f80(math.nan(f64))));
141167}
142168
143test "trunc128.special" {
144 try expect(truncq(0.0) == 0.0);
145 try expect(truncq(-0.0) == -0.0);
146 try expect(math.isPositiveInf(truncq(math.inf(f128))));
147 try expect(math.isNegativeInf(truncq(-math.inf(f128))));
148 try expect(math.isNan(truncq(math.nan(f128))));
169test trunc_f128 {
170 try expect(trunc_f128(1.3) == 1.0);
171 try expect(trunc_f128(-1.3) == -1.0);
172 try expect(math.isPositiveZero(trunc_f128(0.2)));
173 try expect(math.isNegativeZero(trunc_f128(-0.2)));
174 try expect(math.isPositiveZero(trunc_f128(0.0)));
175 try expect(math.isNegativeZero(trunc_f128(-0.0)));
176 try expect(math.isPositiveInf(trunc_f128(math.inf(f128))));
177 try expect(math.isNegativeInf(trunc_f128(-math.inf(f128))));
178 try expect(math.isNan(trunc_f128(math.nan(f128))));
149179}
lib/compiler_rt/truncdfhf2.zig deleted-18
......@@ -1,18 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const truncf = @import("./truncf.zig").truncf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2h, "__aeabi_d2h");
8 }
9 symbol(&__truncdfhf2, "__truncdfhf2");
10}
11
12pub fn __truncdfhf2(a: f64) callconv(.c) compiler_rt.F16T(f64) {
13 return @bitCast(truncf(f16, f64, a));
14}
15
16fn __aeabi_d2h(a: f64) callconv(.{ .arm_aapcs = .{} }) u16 {
17 return @bitCast(truncf(f16, f64, a));
18}
lib/compiler_rt/truncdfsf2.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_d2f, "__aeabi_d2f");
8 } else {
9 symbol(&__truncdfsf2, "__truncdfsf2");
10 }
11}
12
13pub fn __truncdfsf2(a: f64) callconv(.c) f32 {
14 return truncf(f32, f64, a);
15}
16
17fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 {
18 return truncf(f32, f64, a);
19}
lib/compiler_rt/truncf.zig+200-2
......@@ -1,6 +1,204 @@
11const std = @import("std");
22
3pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5
6comptime {
7 if (compiler_rt.want_aeabi) {
8 if (compiler_rt.gnu_f16_abi) {
9 symbol(&__aeabi_f2h, "__gnu_f2h_ieee");
10 } else {
11 symbol(&__aeabi_f2h, "__aeabi_f2h");
12 }
13 symbol(&__aeabi_d2h, "__aeabi_d2h");
14 } else if (compiler_rt.gnu_f16_abi) {
15 symbol(&__truncsfhf2, "__gnu_f2h_ieee");
16 }
17 symbol(&__truncsfhf2, "__truncsfhf2");
18 symbol(&__truncdfhf2, "__truncdfhf2");
19 symbol(&__truncxfhf2, "__truncxfhf2");
20 if (compiler_rt.want_ppc_abi) {
21 symbol(&__trunctfhf2, "__trunckfhf2");
22 } else {
23 symbol(&__trunctfhf2, "__trunctfhf2");
24 }
25
26 if (compiler_rt.want_aeabi) {
27 symbol(&__aeabi_d2f, "__aeabi_d2f");
28 } else {
29 symbol(&__truncdfsf2, "__truncdfsf2");
30 }
31 symbol(&__truncxfsf2, "__truncxfsf2");
32 if (compiler_rt.want_ppc_abi) {
33 symbol(&__trunctfsf2, "__trunckfsf2");
34 } else if (compiler_rt.want_sparc64_abi) {
35 symbol(&_Qp_qtos, "_Qp_qtos");
36 } else if (compiler_rt.want_sparc32_abi) {
37 symbol(&__trunctfsf2, "_Q_qtos");
38 } else {
39 symbol(&__trunctfsf2, "__trunctfsf2");
40 }
41
42 symbol(&__truncxfdf2, "__truncxfdf2");
43
44 if (compiler_rt.want_ppc_abi) {
45 symbol(&__trunctfdf2, "__trunckfdf2");
46 } else if (compiler_rt.want_sparc64_abi) {
47 symbol(&_Qp_qtod, "_Qp_qtod");
48 } else if (compiler_rt.want_sparc32_abi) {
49 symbol(&__trunctfdf2, "_Q_qtod");
50 } else {
51 symbol(&__trunctfdf2, "__trunctfdf2");
52 }
53
54 if (compiler_rt.want_ppc_abi) {
55 symbol(&__trunctfxf2, "__trunckfxf2");
56 } else {
57 symbol(&__trunctfxf2, "__trunctfxf2");
58 }
59}
60
61fn __truncsfhf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f16Conv(f32).Abi {
62 return compiler_rt.f16Conv(f32).toAbi(f16_floatCast_f32(compiler_rt.f32.fromAbi(a)));
63}
64fn __aeabi_f2h(a: u32) callconv(.{ .arm_aapcs = .{} }) u16 {
65 return @bitCast(f16_floatCast_f32(@bitCast(a)));
66}
67pub fn f16_floatCast_f32(a: f32) f16 {
68 return truncf(f16, f32, a);
69}
70
71fn __truncdfhf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f16Conv(f64).Abi {
72 return compiler_rt.f16Conv(f64).toAbi(f16_floatCast_f64(compiler_rt.f64.fromAbi(a)));
73}
74fn __aeabi_d2h(a: u64) callconv(.{ .arm_aapcs = .{} }) u16 {
75 return @bitCast(f16_floatCast_f64(@bitCast(a)));
76}
77pub fn f16_floatCast_f64(a: f64) f16 {
78 return truncf(f16, f64, a);
79}
80
81fn __truncxfhf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f16Conv(f80).Abi {
82 return compiler_rt.f16Conv(f80).toAbi(f16_floatCast_f80(compiler_rt.f80.fromAbi(a)));
83}
84pub fn f16_floatCast_f80(a: f80) f16 {
85 return trunc_f80(f16, a);
86}
87
88fn __trunctfhf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f16Conv(f128).Abi {
89 return compiler_rt.f16Conv(f128).toAbi(f16_floatCast_f128(compiler_rt.f128.fromAbi(a)));
90}
91pub fn f16_floatCast_f128(a: f128) f16 {
92 return truncf(f16, f128, a);
93}
94
95fn __truncdfsf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f32.Abi {
96 return compiler_rt.f32.toAbi(f32_floatCast_f64(compiler_rt.f64.fromAbi(a)));
97}
98fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 {
99 return f32_floatCast_f64(a);
100}
101pub fn f32_floatCast_f64(a: f64) f32 {
102 return truncf(f32, f64, a);
103}
104
105fn __truncxfsf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f32.Abi {
106 return compiler_rt.f32.toAbi(f32_floatCast_f80(compiler_rt.f80.fromAbi(a)));
107}
108pub fn f32_floatCast_f80(a: f80) f32 {
109 return trunc_f80(f32, a);
110}
111
112fn __trunctfsf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f32.Abi {
113 return compiler_rt.f32.toAbi(f32_floatCast_f128(compiler_rt.f128.fromAbi(a)));
114}
115fn _Qp_qtos(a: *const f128) callconv(.c) f32 {
116 return f32_floatCast_f128(a.*);
117}
118pub fn f32_floatCast_f128(a: f128) f32 {
119 return truncf(f32, f128, a);
120}
121
122fn __truncxfdf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f64.Abi {
123 return compiler_rt.f64.toAbi(f64_floatCast_f80(compiler_rt.f80.fromAbi(a)));
124}
125pub fn f64_floatCast_f80(a: f80) f64 {
126 return trunc_f80(f64, a);
127}
128
129fn __trunctfdf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f64.Abi {
130 return compiler_rt.f64.toAbi(f64_floatCast_f128(compiler_rt.f128.fromAbi(a)));
131}
132fn _Qp_qtod(a: *const f128) callconv(.c) f64 {
133 return f64_floatCast_f128(a.*);
134}
135pub fn f64_floatCast_f128(a: f128) f64 {
136 return truncf(f64, f128, a);
137}
138
139fn __trunctfxf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f80.Abi {
140 return compiler_rt.f80.toAbi(f80_floatCast_f128(compiler_rt.f128.fromAbi(a)));
141}
142pub fn f80_floatCast_f128(a: f128) f80 {
143 const src_sig_bits = std.math.floatMantissaBits(f128);
144 const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
145
146 // Various constants whose values follow from the type parameters.
147 // Any reasonable optimizer will fold and propagate all of these.
148 const src_bits = @typeInfo(f128).float.bits;
149 const src_exp_bits = src_bits - src_sig_bits - 1;
150 const src_inf_exp = 0x7FFF;
151
152 const src_inf = src_inf_exp << src_sig_bits;
153 const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
154 const src_abs_mask = src_sign_mask - 1;
155 const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1;
156 const halfway = 1 << (src_sig_bits - dst_sig_bits - 1);
157
158 // Break a into a sign and representation of the absolute value
159 const a_rep: u128 = @bitCast(a);
160 const a_abs = a_rep & src_abs_mask;
161 const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0;
162 const integer_bit = 1 << 63;
163
164 var res: std.math.F80 = undefined;
165
166 if (a_abs > src_inf) {
167 // a is NaN.
168 // Conjure the result by beginning with infinity, setting the qNaN
169 // bit and inserting the (truncated) trailing NaN field.
170 res.exp = 0x7fff;
171 res.fraction = 0x8000000000000000;
172 res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits)));
173 } else {
174 // The exponent of a is within the range of normal numbers in the
175 // destination format. We can convert by simply right-shifting with
176 // rounding, adding the explicit integer bit, and adjusting the exponent
177 res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit;
178 res.exp = @truncate(a_abs >> src_sig_bits);
179
180 const round_bits = a_abs & round_mask;
181 if (round_bits > halfway) {
182 // Round to nearest
183 const ov = @addWithOverflow(res.fraction, 1);
184 res.fraction = ov[0];
185 res.exp += ov[1];
186 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
187 } else if (round_bits == halfway) {
188 // Ties to even
189 const ov = @addWithOverflow(res.fraction, res.fraction & 1);
190 res.fraction = ov[0];
191 res.exp += ov[1];
192 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
193 }
194 if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals
195 }
196
197 res.exp |= sign;
198 return res.toFloat();
199}
200
201inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
4202 const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
5203 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
6204 const srcSigBits = std.math.floatMantissaBits(src_t);
......@@ -99,7 +297,7 @@ pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t
99297 return @bitCast(result);
100298}
101299
102pub inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t {
300inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t {
103301 const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits);
104302 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
105303 const dst_sig_bits = std.math.floatMantissaBits(dst_t);
lib/compiler_rt/truncf_test.zig+160-174
......@@ -1,79 +1,82 @@
11const std = @import("std");
22const testing = std.testing;
33
4const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2;
5const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2;
6const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2;
7const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2;
8const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2;
9const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2;
10const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2;
11
12fn test__truncsfhf2(a: u32, expected: u16) !void {
13 const actual: u16 = @bitCast(__truncsfhf2(@bitCast(a)));
14
15 if (actual == expected) {
16 return;
17 }
4const impl = @import("truncf.zig");
185
19 return error.TestFailure;
6const f16_floatCast_f32 = impl.f16_floatCast_f32;
7const f16_floatCast_f64 = impl.f16_floatCast_f64;
8const f16_floatCast_f80 = impl.f16_floatCast_f80;
9const f16_floatCast_f128 = impl.f16_floatCast_f128;
10
11const f32_floatCast_f64 = impl.f32_floatCast_f64;
12const f32_floatCast_f80 = impl.f32_floatCast_f80;
13const f32_floatCast_f128 = impl.f32_floatCast_f128;
14
15const f64_floatCast_f80 = impl.f64_floatCast_f80;
16const f64_floatCast_f128 = impl.f64_floatCast_f128;
17
18const f80_floatCast_f128 = impl.f80_floatCast_f128;
19
20fn test_f16_floatCast_f32(a: u32, expected: u16) !void {
21 const actual: u16 = @bitCast(f16_floatCast_f32(@bitCast(a)));
22 try testing.expect(actual == expected);
2023}
2124
22test "truncsfhf2" {
23 try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN
24 try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN
25test f16_floatCast_f32 {
26 try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN
27 try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN
2528
26 try test__truncsfhf2(0, 0); // 0
27 try test__truncsfhf2(0x80000000, 0x8000); // -0
29 try test_f16_floatCast_f32(0, 0); // 0
30 try test_f16_floatCast_f32(0x80000000, 0x8000); // -0
2831
29 try test__truncsfhf2(0x7f800000, 0x7c00); // inf
30 try test__truncsfhf2(0xff800000, 0xfc00); // -inf
32 try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf
33 try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf
3134
32 try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf
33 try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf
35 try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf
36 try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf
3437
35 try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
36 try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
38 try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
39 try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
3740
38 try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14
39 try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14
41 try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14
42 try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14
4043
41 try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504
42 try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504
44 try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504
45 try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504
4346
44 try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504
45 try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
47 try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504
48 try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
4649
47 try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504
48 try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
50 try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504
51 try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
4952
50 try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10
51 try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10
53 try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10
54 try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10
5255
53 try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3
54 try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3
56 try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3
57 try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3
5558
56 try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535
57 try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535
59 try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535
60 try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535
5861
59 try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
62 try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
6063
61 try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1
62 try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14
64 try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1
65 try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14
6366
64 try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24
65 try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24
67 try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24
68 try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24
6669
67 try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
68 try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
70 try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
71 try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
6972
70 try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20
71 try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
72 try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
73 try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20
74 try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
75 try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero
7376}
7477
75fn test__truncdfhf2(a: f64, expected: u16) void {
76 const rep: u16 = @bitCast(__truncdfhf2(a));
78fn test_f16_floatCast_f64(a: f64, expected: u16) !void {
79 const rep: u16 = @bitCast(f16_floatCast_f64(a));
7780
7881 if (rep == expected) {
7982 return;
......@@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void {
8487 return;
8588 }
8689 }
87
88 @panic("__truncdfhf2 test failure");
90 return error.TestFailure;
8991}
9092
91fn test__truncdfhf2_raw(a: u64, expected: u16) void {
92 const actual: u16 = @bitCast(__truncdfhf2(@bitCast(a)));
93
94 if (actual == expected) {
95 return;
96 }
97
98 @panic("__truncdfhf2 test failure");
93fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void {
94 const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a)));
95 try testing.expect(actual == expected);
9996}
10097
101test "truncdfhf2" {
102 test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN
103 test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN
98test f16_floatCast_f64 {
99 try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN
100 try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN
104101
105 test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf
106 test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf
102 try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf
103 try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf
107104
108 test__truncdfhf2(0.0, 0x0); // zero
109 test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero
105 try test_f16_floatCast_f64(0.0, 0x0); // zero
106 try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero
110107
111 test__truncdfhf2(3.1415926535, 0x4248);
112 test__truncdfhf2(-3.1415926535, 0xc248);
108 try test_f16_floatCast_f64(3.1415926535, 0x4248);
109 try test_f16_floatCast_f64(-3.1415926535, 0xc248);
113110
114 test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00);
115 test__truncdfhf2(0x1.987124876876324p+12, 0x6e62);
116 test__truncdfhf2(0x1.0p+0, 0x3c00);
117 test__truncdfhf2(0x1.0p-14, 0x0400);
111 try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00);
112 try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62);
113 try test_f16_floatCast_f64(0x1.0p+0, 0x3c00);
114 try test_f16_floatCast_f64(0x1.0p-14, 0x0400);
118115
119116 // denormal
120 test__truncdfhf2(0x1.0p-20, 0x0010);
121 test__truncdfhf2(0x1.0p-24, 0x0001);
122 test__truncdfhf2(-0x1.0p-24, 0x8001);
123 test__truncdfhf2(0x1.5p-25, 0x0001);
117 try test_f16_floatCast_f64(0x1.0p-20, 0x0010);
118 try test_f16_floatCast_f64(0x1.0p-24, 0x0001);
119 try test_f16_floatCast_f64(-0x1.0p-24, 0x8001);
120 try test_f16_floatCast_f64(0x1.5p-25, 0x0001);
124121
125122 // and back to zero
126 test__truncdfhf2(0x1.0p-25, 0x0000);
127 test__truncdfhf2(-0x1.0p-25, 0x8000);
123 try test_f16_floatCast_f64(0x1.0p-25, 0x0000);
124 try test_f16_floatCast_f64(-0x1.0p-25, 0x8000);
128125
129126 // max (precise)
130 test__truncdfhf2(65504.0, 0x7bff);
127 try test_f16_floatCast_f64(65504.0, 0x7bff);
131128
132129 // max (rounded)
133 test__truncdfhf2(65519.0, 0x7bff);
130 try test_f16_floatCast_f64(65519.0, 0x7bff);
134131
135132 // max (to +inf)
136 test__truncdfhf2(65520.0, 0x7c00);
137 test__truncdfhf2(-65520.0, 0xfc00);
138 test__truncdfhf2(65536.0, 0x7c00);
133 try test_f16_floatCast_f64(65520.0, 0x7c00);
134 try test_f16_floatCast_f64(-65520.0, 0xfc00);
135 try test_f16_floatCast_f64(65536.0, 0x7c00);
139136}
140137
141fn test__trunctfsf2(a: f128, expected: u32) void {
142 const x = __trunctfsf2(a);
138fn test_f32_floatCast_f128(a: f128, expected: u32) !void {
139 const x = f32_floatCast_f128(a);
143140
144141 const rep: u32 = @bitCast(x);
145142 if (rep == expected) {
......@@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void {
151148 return;
152149 }
153150 }
154
155 @panic("__trunctfsf2 test failure");
151 return error.TestFailure;
156152}
157153
158test "trunctfsf2" {
154test f32_floatCast_f128 {
159155 // qnan
160 test__trunctfsf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
156 try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
161157 // nan
162 test__trunctfsf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
158 try test_f32_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
163159 // inf
164 test__trunctfsf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000);
160 try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000);
165161 // zero
166 test__trunctfsf2(0.0, 0x0);
162 try test_f32_floatCast_f128(0.0, 0x0);
167163
168 test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
169 test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
170 test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
171 test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
164 try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
165 try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
166 try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
167 try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
172168}
173169
174fn test__trunctfdf2(a: f128, expected: u64) void {
175 const x = __trunctfdf2(a);
170fn test_f64_floatCast_f128(a: f128, expected: u64) !void {
171 const x = f64_floatCast_f128(a);
176172
177173 const rep: u64 = @bitCast(x);
178174 if (rep == expected) {
......@@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void {
184180 return;
185181 }
186182 }
187
188 @panic("__trunctfsf2 test failure");
183 return error.TestFailure;
189184}
190185
191test "trunctfdf2" {
186test f64_floatCast_f128 {
192187 // qnan
193 test__trunctfdf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);
188 try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);
194189 // nan
195 test__trunctfdf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000);
190 try test_f64_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000);
196191 // inf
197 test__trunctfdf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000);
192 try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000);
198193 // zero
199 test__trunctfdf2(0.0, 0x0);
194 try test_f64_floatCast_f128(0.0, 0x0);
200195
201 test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
202 test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
203 test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
204 test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
196 try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb);
197 try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7);
198 try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000);
199 try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab);
205200}
206201
207fn test__truncdfsf2(a: f64, expected: u32) void {
208 const x = __truncdfsf2(a);
202fn test_f32_floatCast_f64(a: f64, expected: u32) !void {
203 const x = f32_floatCast_f64(a);
209204
210205 const rep: u32 = @bitCast(x);
211206 if (rep == expected) {
......@@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void {
217212 return;
218213 }
219214 }
220
221 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
222
223 @panic("__trunctfsf2 test failure");
215 return error.TestFailure;
224216}
225217
226test "truncdfsf2" {
218test f32_floatCast_f64 {
227219 // nan & qnan
228 test__truncdfsf2(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000);
229 test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000);
220 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000);
221 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000);
230222 // inf
231 test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000);
232 test__truncdfsf2(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000);
223 try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000);
224 try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000);
233225
234 test__truncdfsf2(0.0, 0x0);
235 test__truncdfsf2(1.0, 0x3f800000);
236 test__truncdfsf2(-1.0, 0xbf800000);
226 try test_f32_floatCast_f64(0.0, 0x0);
227 try test_f32_floatCast_f64(1.0, 0x3f800000);
228 try test_f32_floatCast_f64(-1.0, 0xbf800000);
237229
238230 // huge number becomes inf
239 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
231 try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000);
240232}
241233
242fn test__trunctfhf2(a: f128, expected: u16) void {
243 const x = __trunctfhf2(a);
234fn test_f16_floatCast_f128(a: f128, expected: u16) !void {
235 const x = f16_floatCast_f128(a);
244236
245237 const rep: u16 = @bitCast(x);
246 if (rep == expected) {
247 return;
248 }
249
250 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
251
252 @panic("__trunctfhf2 test failure");
238 try testing.expect(rep == expected);
253239}
254240
255test "trunctfhf2" {
241test f16_floatCast_f128 {
256242 // qNaN
257 test__trunctfhf2(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
243 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
258244 // NaN
259 test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
245 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
260246 // inf
261 test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
262 test__trunctfhf2(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00);
247 try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
248 try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00);
263249 // zero
264 test__trunctfhf2(0.0, 0x0);
265 test__trunctfhf2(-0.0, 0x8000);
266
267 test__trunctfhf2(3.1415926535, 0x4248);
268 test__trunctfhf2(-3.1415926535, 0xc248);
269 test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);
270 test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);
271 test__trunctfhf2(0x1.0p+0, 0x3c00);
272 test__trunctfhf2(0x1.0p-14, 0x0400);
250 try test_f16_floatCast_f128(0.0, 0x0);
251 try test_f16_floatCast_f128(-0.0, 0x8000);
252
253 try test_f16_floatCast_f128(3.1415926535, 0x4248);
254 try test_f16_floatCast_f128(-3.1415926535, 0xc248);
255 try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00);
256 try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62);
257 try test_f16_floatCast_f128(0x1.0p+0, 0x3c00);
258 try test_f16_floatCast_f128(0x1.0p-14, 0x0400);
273259 // denormal
274 test__trunctfhf2(0x1.0p-20, 0x0010);
275 test__trunctfhf2(0x1.0p-24, 0x0001);
276 test__trunctfhf2(-0x1.0p-24, 0x8001);
277 test__trunctfhf2(0x1.5p-25, 0x0001);
260 try test_f16_floatCast_f128(0x1.0p-20, 0x0010);
261 try test_f16_floatCast_f128(0x1.0p-24, 0x0001);
262 try test_f16_floatCast_f128(-0x1.0p-24, 0x8001);
263 try test_f16_floatCast_f128(0x1.5p-25, 0x0001);
278264 // and back to zero
279 test__trunctfhf2(0x1.0p-25, 0x0000);
280 test__trunctfhf2(-0x1.0p-25, 0x8000);
265 try test_f16_floatCast_f128(0x1.0p-25, 0x0000);
266 try test_f16_floatCast_f128(-0x1.0p-25, 0x8000);
281267 // max (precise)
282 test__trunctfhf2(65504.0, 0x7bff);
268 try test_f16_floatCast_f128(65504.0, 0x7bff);
283269 // max (rounded)
284 test__trunctfhf2(65519.0, 0x7bff);
270 try test_f16_floatCast_f128(65519.0, 0x7bff);
285271 // max (to +inf)
286 test__trunctfhf2(65520.0, 0x7c00);
287 test__trunctfhf2(65536.0, 0x7c00);
288 test__trunctfhf2(-65520.0, 0xfc00);
289
290 test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
291 test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
292 test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
293 test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
272 try test_f16_floatCast_f128(65520.0, 0x7c00);
273 try test_f16_floatCast_f128(65536.0, 0x7c00);
274 try test_f16_floatCast_f128(-65520.0, 0xfc00);
275
276 try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
277 try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
278 try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
279 try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
294280}
295281
296test "trunctfxf2" {
297 try test__trunctfxf2(1.5, 1.5);
298 try test__trunctfxf2(2.5, 2.5);
299 try test__trunctfxf2(-2.5, -2.5);
300 try test__trunctfxf2(0.0, 0.0);
282fn test_f80_floatCast_f128(a: f128, expected: f80) !void {
283 const x = f80_floatCast_f128(a);
284 try testing.expect(x == expected);
301285}
302286
303fn test__trunctfxf2(a: f128, expected: f80) !void {
304 const x = __trunctfxf2(a);
305 try testing.expect(x == expected);
287test f80_floatCast_f128 {
288 try test_f80_floatCast_f128(1.5, 1.5);
289 try test_f80_floatCast_f128(2.5, 2.5);
290 try test_f80_floatCast_f128(-2.5, -2.5);
291 try test_f80_floatCast_f128(0.0, 0.0);
306292}
lib/compiler_rt/truncsfhf2.zig deleted-24
......@@ -1,24 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 if (compiler_rt.gnu_f16_abi) {
7 symbol(&__gnu_f2h_ieee, "__gnu_f2h_ieee");
8 } else if (compiler_rt.want_aeabi) {
9 symbol(&__aeabi_f2h, "__aeabi_f2h");
10 }
11 symbol(&__truncsfhf2, "__truncsfhf2");
12}
13
14pub fn __truncsfhf2(a: f32) callconv(.c) compiler_rt.F16T(f32) {
15 return @bitCast(truncf(f16, f32, a));
16}
17
18fn __gnu_f2h_ieee(a: f32) callconv(.c) compiler_rt.F16T(f32) {
19 return @bitCast(truncf(f16, f32, a));
20}
21
22fn __aeabi_f2h(a: f32) callconv(.{ .arm_aapcs = .{} }) u16 {
23 return @bitCast(truncf(f16, f32, a));
24}
lib/compiler_rt/trunctfdf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = compiler_rt.symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__trunctfdf2, "__trunckfdf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtod, "_Qp_qtod");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__trunctfdf2, "_Q_qtod");
12 }
13 symbol(&__trunctfdf2, "__trunctfdf2");
14}
15
16pub fn __trunctfdf2(a: f128) callconv(.c) f64 {
17 return truncf(f64, f128, a);
18}
19
20fn _Qp_qtod(a: *const f128) callconv(.c) f64 {
21 return truncf(f64, f128, a.*);
22}
lib/compiler_rt/trunctfhf2.zig deleted-14
......@@ -1,14 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const truncf = @import("./truncf.zig").truncf;
4
5comptime {
6 symbol(&__trunctfhf2, "__trunctfhf2");
7 if (compiler_rt.want_ppc_abi) {
8 symbol(&__trunctfhf2, "__trunckfhf2");
9 }
10}
11
12pub fn __trunctfhf2(a: f128) callconv(.c) compiler_rt.F16T(f128) {
13 return @bitCast(truncf(f16, f128, a));
14}
lib/compiler_rt/trunctfsf2.zig deleted-22
......@@ -1,22 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const truncf = @import("./truncf.zig").truncf;
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_ppc_abi) {
7 symbol(&__trunctfsf2, "__trunckfsf2");
8 } else if (compiler_rt.want_sparc64_abi) {
9 symbol(&_Qp_qtos, "_Qp_qtos");
10 } else if (compiler_rt.want_sparc32_abi) {
11 symbol(&__trunctfsf2, "_Q_qtos");
12 }
13 symbol(&__trunctfsf2, "__trunctfsf2");
14}
15
16pub fn __trunctfsf2(a: f128) callconv(.c) f32 {
17 return truncf(f32, f128, a);
18}
19
20fn _Qp_qtos(a: *const f128) callconv(.c) f32 {
21 return truncf(f32, f128, a.*);
22}
lib/compiler_rt/trunctfxf2.zig deleted-67
......@@ -1,67 +0,0 @@
1const math = @import("std").math;
2const compiler_rt = @import("../compiler_rt.zig");
3const symbol = compiler_rt.symbol;
4const trunc_f80 = @import("./truncf.zig").trunc_f80;
5
6comptime {
7 symbol(&__trunctfxf2, "__trunctfxf2");
8}
9
10pub fn __trunctfxf2(a: f128) callconv(.c) f80 {
11 const src_sig_bits = math.floatMantissaBits(f128);
12 const dst_sig_bits = math.floatMantissaBits(f80) - 1; // -1 for the integer bit
13
14 // Various constants whose values follow from the type parameters.
15 // Any reasonable optimizer will fold and propagate all of these.
16 const src_bits = @typeInfo(f128).float.bits;
17 const src_exp_bits = src_bits - src_sig_bits - 1;
18 const src_inf_exp = 0x7FFF;
19
20 const src_inf = src_inf_exp << src_sig_bits;
21 const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
22 const src_abs_mask = src_sign_mask - 1;
23 const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1;
24 const halfway = 1 << (src_sig_bits - dst_sig_bits - 1);
25
26 // Break a into a sign and representation of the absolute value
27 const a_rep = @as(u128, @bitCast(a));
28 const a_abs = a_rep & src_abs_mask;
29 const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0;
30 const integer_bit = 1 << 63;
31
32 var res: math.F80 = undefined;
33
34 if (a_abs > src_inf) {
35 // a is NaN.
36 // Conjure the result by beginning with infinity, setting the qNaN
37 // bit and inserting the (truncated) trailing NaN field.
38 res.exp = 0x7fff;
39 res.fraction = 0x8000000000000000;
40 res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits)));
41 } else {
42 // The exponent of a is within the range of normal numbers in the
43 // destination format. We can convert by simply right-shifting with
44 // rounding, adding the explicit integer bit, and adjusting the exponent
45 res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit;
46 res.exp = @truncate(a_abs >> src_sig_bits);
47
48 const round_bits = a_abs & round_mask;
49 if (round_bits > halfway) {
50 // Round to nearest
51 const ov = @addWithOverflow(res.fraction, 1);
52 res.fraction = ov[0];
53 res.exp += ov[1];
54 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
55 } else if (round_bits == halfway) {
56 // Ties to even
57 const ov = @addWithOverflow(res.fraction, res.fraction & 1);
58 res.fraction = ov[0];
59 res.exp += ov[1];
60 res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry
61 }
62 if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals
63 }
64
65 res.exp |= sign;
66 return res.toFloat();
67}
lib/compiler_rt/truncxfdf2.zig deleted-10
......@@ -1,10 +0,0 @@
1const symbol = @import("../compiler_rt.zig").symbol;
2const trunc_f80 = @import("./truncf.zig").trunc_f80;
3
4comptime {
5 symbol(&__truncxfdf2, "__truncxfdf2");
6}
7
8fn __truncxfdf2(a: f80) callconv(.c) f64 {
9 return trunc_f80(f64, a);
10}
lib/compiler_rt/truncxfhf2.zig deleted-11
......@@ -1,11 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const symbol = @import("../compiler_rt.zig").symbol;
3const trunc_f80 = @import("./truncf.zig").trunc_f80;
4
5comptime {
6 symbol(&__truncxfhf2, "__truncxfhf2");
7}
8
9fn __truncxfhf2(a: f80) callconv(.c) compiler_rt.F16T(f80) {
10 return @bitCast(trunc_f80(f16, a));
11}
lib/compiler_rt/truncxfsf2.zig deleted-10
......@@ -1,10 +0,0 @@
1const trunc_f80 = @import("./truncf.zig").trunc_f80;
2const symbol = @import("../compiler_rt.zig").symbol;
3
4comptime {
5 symbol(&__truncxfsf2, "__truncxfsf2");
6}
7
8fn __truncxfsf2(a: f80) callconv(.c) f32 {
9 return trunc_f80(f32, a);
10}
lib/compiler_rt/udivmodei4.zig+1-1
......@@ -6,7 +6,7 @@ const shr = std.math.shr;
66const shl = std.math.shl;
77
88const compiler_rt = @import("../compiler_rt.zig");
9const symbol = @import("../compiler_rt.zig").symbol;
9const symbol = compiler_rt.symbol;
1010
1111const max_limbs = @divCeil(65535, 32); // max supported type is u65535
1212
lib/compiler_rt/unorddf2.zig deleted-19
......@@ -1,19 +0,0 @@
1const compiler_rt = @import("../compiler_rt.zig");
2const comparef = @import("./comparef.zig");
3const symbol = @import("../compiler_rt.zig").symbol;
4
5comptime {
6 if (compiler_rt.want_aeabi) {
7 symbol(&__aeabi_dcmpun, "__aeabi_dcmpun");
8 } else {
9 symbol(&__unorddf2, "__unorddf2");
10 }
11}
12
13pub fn __unorddf2(a: f64, b: f64) callconv(.c) i32 {
14 return comparef.unordcmp(f64, a, b);
15}
16
17fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 {
18 return comparef.unordcmp(f64, a, b);
19}
lib/std/Io/Semaphore.zig-2
......@@ -4,8 +4,6 @@
44//! This API supports static initialization and does not require deinitialization.
55const Semaphore = @This();
66
7const builtin = @import("builtin");
8
97const std = @import("../std.zig");
108const Io = std.Io;
119const testing = std.testing;
lib/std/Io/Writer.zig+9-9
......@@ -874,7 +874,7 @@ pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize {
874874}
875875
876876/// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes.
877pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void {
877pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.lang.Endian) Error!void {
878878 var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined;
879879 std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
880880 return w.writeAll(&bytes);
......@@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built
882882
883883/// The function is inline to avoid the dead code in case `endian` is
884884/// comptime-known and matches host endianness.
885pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void {
885pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.lang.Endian) Error!void {
886886 switch (@typeInfo(@TypeOf(value))) {
887887 .@"struct" => |info| switch (info.layout) {
888888 .auto => @compileError("ill-defined memory layout"),
......@@ -907,7 +907,7 @@ pub inline fn writeSliceEndian(
907907 w: *Writer,
908908 Elem: type,
909909 slice: []const Elem,
910 endian: std.builtin.Endian,
910 endian: std.lang.Endian,
911911) Error!void {
912912 switch (@typeInfo(Elem)) {
913913 .@"struct" => |info| comptime assert(info.layout != .auto),
......@@ -2817,12 +2817,12 @@ pub const Allocating = struct {
28172817 }
28182818
28192819 test Allocating {
2820 try testAllocating(.fromByteUnits(1));
2821 try testAllocating(.fromByteUnits(4));
2822 try testAllocating(.fromByteUnits(8));
2823 try testAllocating(.fromByteUnits(16));
2824 try testAllocating(.fromByteUnits(32));
2825 try testAllocating(.fromByteUnits(64));
2820 try testAllocating(.@"1");
2821 try testAllocating(.@"4");
2822 try testAllocating(.@"8");
2823 try testAllocating(.@"16");
2824 try testAllocating(.@"32");
2825 try testAllocating(.@"64");
28262826 }
28272827};
28282828
lib/std/Random/RomuTrio.zig-1
......@@ -122,7 +122,6 @@ test fill {
122122}
123123
124124test "buf seeding test" {
125 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
126125 const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 });
127126 const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 };
128127 var r = RomuTrio.init(0);
lib/std/Random/Xoshiro256.zig-2
......@@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void {
8989}
9090
9191test "sequence" {
92 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
93
9492 var r = Xoshiro256.init(0);
9593
9694 const seq1 = [_]u64{
lib/std/Target.zig+26-131
......@@ -1797,6 +1797,7 @@ pub const Cpu = struct {
17971797
17981798 .x86_sysv,
17991799 .x86_win,
1800 .x86_mingw,
18001801 .x86_stdcall,
18011802 .x86_fastcall,
18021803 .x86_thiscall,
......@@ -3066,9 +3067,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth {
30663067/// Default signedness of `char` for the native C compiler for this target
30673068/// Note that char signedness is implementation-defined and many compilers provide
30683069/// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char
3069pub fn cCharSignedness(target: *const Target) std.builtin.Signedness {
3070/// Returns `null` if no C ABI is defined for this target.
3071pub fn cCharSignedness(target: *const Target) ?std.builtin.Signedness {
3072 switch (target.os.tag) {
3073 .opengl => return null,
3074 else => {},
3075 }
30703076 if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed;
3071
30723077 return switch (target.cpu.arch) {
30733078 .aarch64,
30743079 .aarch64_be,
......@@ -3114,7 +3119,8 @@ pub const CType = enum {
31143119 longdouble,
31153120};
31163121
3117pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {
3122/// Returns `null` if no C ABI is defined for this target.
3123pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 {
31183124 return switch (c_type) {
31193125 .char,
31203126 .short,
......@@ -3127,18 +3133,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {
31273133 .ulonglong,
31283134 .float,
31293135 .double,
3130 => @divExact(cTypeBitSize(t, c_type), 8),
3136 => @divExact(cTypeBitSize(t, c_type) orelse return null, 8),
31313137
3132 .longdouble => switch (cTypeBitSize(t, c_type)) {
3138 .longdouble => switch (cTypeBitSize(t, c_type) orelse return null) {
31333139 64 => 8,
3134 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, .longdouble))),
3140 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, c_type).?)),
31353141 128 => 16,
31363142 else => unreachable,
31373143 },
31383144 };
31393145}
31403146
3141pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
3147/// Returns `null` if no C ABI is defined for this target.
3148pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 {
31423149 switch (target.os.tag) {
31433150 .freestanding,
31443151 .other,
......@@ -3459,15 +3466,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
34593466 .longlong, .ulonglong, .longdouble => return 64,
34603467 },
34613468
3469 .opengl => return null,
3470
34623471 .ps3,
34633472 .contiki,
34643473 .managarm,
3465 .opengl,
34663474 => @panic("specify the C integer and float type sizes for this OS"),
34673475 }
34683476}
34693477
3470pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
3478/// Returns `null` if no C ABI is defined for this target.
3479pub fn cTypeAlignment(target: *const Target, c_type: CType) ?u16 {
34713480 // Overrides for unusual alignments
34723481 switch (target.cpu.arch) {
34733482 .avr,
......@@ -3500,7 +3509,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
35003509
35013510 // Next-power-of-two-aligned, up to a maximum.
35023511 return @min(
3503 std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8),
3512 std.math.ceilPowerOfTwoAssert(u16, ((cTypeBitSize(target, c_type) orelse return null) + 7) / 8),
35043513 @as(u16, switch (target.cpu.arch) {
35053514 .msp430,
35063515 .x86_16,
......@@ -3575,120 +3584,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
35753584 );
35763585}
35773586
3578pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 {
3579 // Overrides for unusual alignments
3580 switch (target.cpu.arch) {
3581 .arc, .arceb => switch (c_type) {
3582 .longdouble => return 4,
3583 else => {},
3584 },
3585 .avr,
3586 .ez80,
3587 => return 1,
3588 .x86 => switch (target.os.tag) {
3589 .windows, .uefi => switch (c_type) {
3590 .longdouble => switch (target.abi) {
3591 .gnu => return 4,
3592 else => return 8,
3593 },
3594 else => {},
3595 },
3596 else => switch (c_type) {
3597 .longdouble => return 4,
3598 else => {},
3599 },
3600 },
3601 .m68k => switch (c_type) {
3602 .int, .uint, .long, .ulong => return 2,
3603 else => {},
3604 },
3605 .wasm32, .wasm64 => switch (target.os.tag) {
3606 .emscripten => switch (c_type) {
3607 .longdouble => return 8,
3608 else => {},
3609 },
3610 else => {},
3611 },
3612 else => {},
3613 }
3614
3615 // Next-power-of-two-aligned, up to a maximum.
3616 return @min(
3617 std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8),
3618 @as(u16, switch (target.cpu.arch) {
3619 .x86_16,
3620 .msp430,
3621 => 2,
3622
3623 .arc,
3624 .arceb,
3625 .csky,
3626 .kalimba,
3627 .microblaze,
3628 .microblazeel,
3629 .or1k,
3630 .propeller,
3631 .sh,
3632 .sheb,
3633 .xcore,
3634 .xtensa,
3635 .xtensaeb,
3636 => 4,
3637
3638 .amdgcn,
3639 .arm,
3640 .armeb,
3641 .bpfeb,
3642 .bpfel,
3643 .hexagon,
3644 .hppa,
3645 .lanai,
3646 .m68k,
3647 .m88k,
3648 .mips,
3649 .mipsel,
3650 .nvptx,
3651 .nvptx64,
3652 .s390x,
3653 .sparc,
3654 .thumb,
3655 .thumbeb,
3656 .x86,
3657 => 8,
3658
3659 .aarch64,
3660 .aarch64_be,
3661 .alpha,
3662 .hppa64,
3663 .kvx,
3664 .loongarch32,
3665 .loongarch64,
3666 .mips64,
3667 .mips64el,
3668 .powerpc,
3669 .powerpcle,
3670 .powerpc64,
3671 .powerpc64le,
3672 .riscv32,
3673 .riscv32be,
3674 .riscv64,
3675 .riscv64be,
3676 .sparc64,
3677 .spirv32,
3678 .spirv64,
3679 .ve,
3680 .wasm32,
3681 .wasm64,
3682 .x86_64,
3683 => 16,
3684
3685 .avr,
3686 .ez80,
3687 => unreachable, // Handled above.
3688 }),
3689 );
3690}
3691
36923587pub fn cMaxIntAlignment(target: *const Target) u16 {
36933588 return switch (target.cpu.arch) {
36943589 .avr,
......@@ -3712,6 +3607,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
37123607 .xcore,
37133608 => 4,
37143609
3610 .x86 => switch (target.os.tag) {
3611 else => 4,
3612 .uefi, .windows => 8,
3613 },
3614
37153615 .arm,
37163616 .armeb,
37173617 .hexagon,
......@@ -3730,7 +3630,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
37303630 .sparc,
37313631 .thumb,
37323632 .thumbeb,
3733 .x86,
37343633 .xtensa,
37353634 .xtensaeb,
37363635 => 8,
......@@ -3766,18 +3665,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
37663665pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {
37673666 return switch (target.cpu.arch) {
37683667 .x86_64 => switch (target.os.tag) {
3769 .windows,
3770 .uefi,
3771 => .{ .x86_64_win = .{} },
3668 .windows, .uefi => .{ .x86_64_win = .{} },
37723669 else => switch (target.abi) {
37733670 .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },
37743671 else => .{ .x86_64_sysv = .{} },
37753672 },
37763673 },
37773674 .x86 => switch (target.os.tag) {
3778 .windows,
3779 .uefi,
3780 => .{ .x86_win = .{} },
3675 .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} },
37813676 else => .{ .x86_sysv = .{} },
37823677 },
37833678 .x86_16 => .{ .x86_16_cdecl = .{} },
lib/std/bit_set.zig-2
......@@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void {
17071707}
17081708
17091709test Integer {
1710 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1711
17121710 try testStaticBitSet(Integer(0));
17131711 try testStaticBitSet(Integer(1));
17141712 try testStaticBitSet(Integer(2));
lib/std/crypto/Certificate.zig+1-1
......@@ -1211,7 +1211,7 @@ pub const rsa = struct {
12111211 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
12121212 0x00, 0x04, 0x40,
12131213 },
1214 else => @compileError("unreachable"),
1214 else => comptime unreachable,
12151215 };
12161216 em_index -= hash_der.len;
12171217 @memcpy(em[em_index..][0..hash_der.len], hash_der);
lib/std/crypto/aes.zig+2-2
......@@ -6,9 +6,9 @@ const has_aesni = builtin.cpu.has(.x86, .aes);
66const has_avx = builtin.cpu.has(.x86, .avx);
77const has_armaes = builtin.cpu.has(.aarch64, .aes);
88// C backend doesn't currently support passing vectors to inline asm.
9const impl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c and has_aesni and has_avx) impl: {
9const impl = if (builtin.cpu.arch == .x86_64 and has_aesni and has_avx) impl: {
1010 break :impl @import("aes/aesni.zig");
11} else if (builtin.cpu.arch == .aarch64 and builtin.zig_backend != .stage2_c and has_armaes) impl: {
11} else if (builtin.cpu.arch == .aarch64 and (builtin.zig_backend != .stage2_c or !builtin.os.tag.isDarwin()) and has_armaes) impl: {
1212 break :impl @import("aes/armcrypto.zig");
1313} else impl: {
1414 break :impl @import("aes/soft.zig");
lib/std/crypto/aes_ocb.zig-10
......@@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes;
262262const testing = std.testing;
263263
264264test "AesOcb test vector 1" {
265 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
266
267265 var k: [Aes128Ocb.key_length]u8 = undefined;
268266 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
269267 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -281,8 +279,6 @@ test "AesOcb test vector 1" {
281279}
282280
283281test "AesOcb test vector 2" {
284 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
285
286282 var k: [Aes128Ocb.key_length]u8 = undefined;
287283 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
288284 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -303,8 +299,6 @@ test "AesOcb test vector 2" {
303299}
304300
305301test "AesOcb test vector 3" {
306 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
307
308302 var k: [Aes128Ocb.key_length]u8 = undefined;
309303 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
310304 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -329,8 +323,6 @@ test "AesOcb test vector 3" {
329323}
330324
331325test "AesOcb test vector 4" {
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
333
334326 var k: [Aes128Ocb.key_length]u8 = undefined;
335327 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
336328 var tag: [Aes128Ocb.tag_length]u8 = undefined;
......@@ -356,8 +348,6 @@ test "AesOcb test vector 4" {
356348}
357349
358350test "AesOcb in-place encryption-decryption" {
359 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
360
361351 var k: [Aes128Ocb.key_length]u8 = undefined;
362352 var nonce: [Aes128Ocb.nonce_length]u8 = undefined;
363353 var tag: [Aes128Ocb.tag_length]u8 = undefined;
lib/std/crypto/ecdsa.zig-21
......@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
21const std = @import("std");
32const crypto = std.crypto;
43const fmt = std.fmt;
......@@ -415,8 +414,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
415414}
416415
417416test "Basic operations over EcdsaP384Sha384" {
418 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
419
420417 const io = testing.io;
421418 const Scheme = EcdsaP384Sha384;
422419 const kp = Scheme.KeyPair.generate(io);
......@@ -432,8 +429,6 @@ test "Basic operations over EcdsaP384Sha384" {
432429}
433430
434431test "Basic operations over Secp256k1" {
435 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
436
437432 const io = testing.io;
438433 const Scheme = EcdsaSecp256k1Sha256oSha256;
439434 const kp = Scheme.KeyPair.generate(io);
......@@ -449,8 +444,6 @@ test "Basic operations over Secp256k1" {
449444}
450445
451446test "Basic operations over EcdsaP384Sha256" {
452 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
453
454447 const io = testing.io;
455448 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
456449 const kp = Scheme.KeyPair.generate(io);
......@@ -466,8 +459,6 @@ test "Basic operations over EcdsaP384Sha256" {
466459}
467460
468461test "Verifying a existing signature with EcdsaP384Sha256" {
469 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
470
471462 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
472463 // zig fmt: off
473464 const sk_bytes = [_]u8{
......@@ -503,8 +494,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" {
503494}
504495
505496test "Prehashed message operations" {
506 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
507
508497 const io = testing.io;
509498
510499 const Scheme = EcdsaP256Sha256;
......@@ -539,8 +528,6 @@ const TestVector = struct {
539528};
540529
541530test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {
542 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
543
544531 const vectors: []const TestVector = &.{
545532 // well-formed DER encoding -> expected valid
546533 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" },
......@@ -711,8 +698,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" {
711698}
712699
713700test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {
714 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
715
716701 const vectors: []const TestVector = &.{
717702 // S encoded with negative sign -> expected invalid
718703 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" },
......@@ -1026,8 +1011,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" {
10261011}
10271012
10281013test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {
1029 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1030
10311014 const vectors: []const TestVector = &.{
10321015 // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid
10331016 .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" },
......@@ -1243,8 +1226,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" {
12431226}
12441227
12451228test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" {
1246 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1247
12481229 const vectors: []const TestVector = &.{
12491230 // S encoded with negative sign -> expected invalid
12501231 .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" },
......@@ -1631,8 +1612,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void {
16311612}
16321613
16331614test "Sec1 encoding/decoding" {
1634 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1635
16361615 const io = testing.io;
16371616 const Scheme = EcdsaP384Sha384;
16381617 const kp = Scheme.KeyPair.generate(io);
lib/std/crypto/ff.zig-4
......@@ -966,8 +966,6 @@ const ct_unprotected = struct {
966966};
967967
968968test "finite field arithmetic" {
969 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
970
971969 const M = Modulus(256);
972970 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);
973971 var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);
......@@ -1066,8 +1064,6 @@ test "finite field arithmetic" {
10661064}
10671065
10681066fn testCt(ct_: anytype) !void {
1069 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1070
10711067 const l0: Limb = 0;
10721068 const l1: Limb = 1;
10731069 try testing.expectEqual(l1, ct_.select(true, l1, l0));
lib/std/crypto/pcurves/p384.zig+4-6
......@@ -56,7 +56,7 @@ pub const P384 = struct {
5656 }
5757
5858 /// Create a point from serialized affine coordinates.
59 pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!P384 {
59 pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!P384 {
6060 const x = try Fe.fromBytes(xs, endian);
6161 const y = try Fe.fromBytes(ys, endian);
6262 return fromAffineCoordinates(.{ .x = x, .y = y });
......@@ -395,7 +395,7 @@ pub const P384 = struct {
395395
396396 /// Multiply an elliptic curve point by a scalar.
397397 /// Return error.IdentityElement if the result is the identity element.
398 pub fn mul(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 {
398 pub fn mul(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 {
399399 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
400400 if (p.is_base) {
401401 return pcMul16(&basePointPc, s, false);
......@@ -407,7 +407,7 @@ pub const P384 = struct {
407407
408408 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
409409 /// This can be used for signature verification.
410 pub fn mulPublic(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 {
410 pub fn mulPublic(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 {
411411 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
412412 if (p.is_base) {
413413 return pcMul16(&basePointPc, s, true);
......@@ -419,7 +419,7 @@ pub const P384 = struct {
419419
420420 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
421421 /// This can be used for signature verification.
422 pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 {
422 pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 {
423423 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);
424424 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);
425425 try p1.rejectIdentity();
......@@ -478,7 +478,5 @@ pub const AffineCoordinates = struct {
478478};
479479
480480test {
481 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
482
483481 _ = @import("tests/p384.zig");
484482}
lib/std/crypto/pcurves/secp256k1.zig+5-7
......@@ -51,7 +51,7 @@ pub const Secp256k1 = struct {
5151 };
5252
5353 /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L).
54 pub fn splitScalar(s: [32]u8, endian: std.builtin.Endian) NonCanonicalError!SplitScalar {
54 pub fn splitScalar(s: [32]u8, endian: std.lang.Endian) NonCanonicalError!SplitScalar {
5555 const b1_neg_s = comptime s: {
5656 var buf: [32]u8 = undefined;
5757 mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little);
......@@ -109,7 +109,7 @@ pub const Secp256k1 = struct {
109109 }
110110
111111 /// Create a point from serialized affine coordinates.
112 pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!Secp256k1 {
112 pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!Secp256k1 {
113113 const x = try Fe.fromBytes(xs, endian);
114114 const y = try Fe.fromBytes(ys, endian);
115115 return fromAffineCoordinates(.{ .x = x, .y = y });
......@@ -423,7 +423,7 @@ pub const Secp256k1 = struct {
423423
424424 /// Multiply an elliptic curve point by a scalar.
425425 /// Return error.IdentityElement if the result is the identity element.
426 pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 {
426 pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 {
427427 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
428428 if (p.is_base) {
429429 return pcMul16(&basePointPc, s, false);
......@@ -435,7 +435,7 @@ pub const Secp256k1 = struct {
435435
436436 /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
437437 /// This can be used for signature verification.
438 pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 {
438 pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 {
439439 const s = if (endian == .little) s_ else Fe.orderSwap(s_);
440440 const zero = comptime scalar.Scalar.zero.toBytes(.little);
441441 if (mem.eql(u8, &zero, &s)) {
......@@ -497,7 +497,7 @@ pub const Secp256k1 = struct {
497497
498498 /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
499499 /// This can be used for signature verification.
500 pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 {
500 pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 {
501501 const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_);
502502 const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_);
503503 try p1.rejectIdentity();
......@@ -556,7 +556,5 @@ pub const AffineCoordinates = struct {
556556};
557557
558558test {
559 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
560
561559 _ = @import("tests/secp256k1.zig");
562560}
lib/std/debug/cpu_context.zig+2
......@@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) {
20202020 .mips64el,
20212021 .or1k,
20222022 .s390x,
2023 .sh,
2024 .sheb,
20232025 .x86,
20242026 .x86_64,
20252027 .xtensa,
lib/std/fmt.zig-2
......@@ -1082,8 +1082,6 @@ test "float.libc.sanity" {
10821082}
10831083
10841084test "union" {
1085 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1086
10871085 const TU = union(enum) {
10881086 float: f32,
10891087 int: u32,
lib/std/fmt/float.zig+1-1
......@@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
6565
6666 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
6767 const tables = switch (DT) {
68 u64 => if (@import("builtin").mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull,
68 u64 => if (builtin.mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull,
6969 u128 => &Backend128_Tables,
7070 else => unreachable,
7171 };
lib/std/fs/test.zig+2-3
......@@ -2205,7 +2205,7 @@ test "'.' and '..' in absolute functions" {
22052205}
22062206
22072207test "chmod" {
2208 if (native_os == .windows or native_os == .wasi) return;
2208 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
22092209
22102210 const io = testing.io;
22112211
......@@ -2228,8 +2228,7 @@ test "chmod" {
22282228}
22292229
22302230test "change ownership" {
2231 if (native_os == .windows or native_os == .wasi)
2232 return error.SkipZigTest;
2231 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
22332232
22342233 const io = testing.io;
22352234
lib/std/hash/auto_hash.zig+1-1
......@@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 {
225225
226226test "typeContainsSlice" {
227227 comptime {
228 try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type)));
228 try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type)));
229229
230230 try testing.expect(typeContainsSlice([]const u8));
231231 try testing.expect(!typeContainsSlice(u8));
lib/std/hash/xxhash.zig-4
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const mem = std.mem;
43const expectEqual = std.testing.expectEqual;
54
......@@ -788,7 +787,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64)
788787}
789788
790789test "xxhash3" {
791 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
792790 const H = XxHash3;
793791 // Non-Seeded Tests
794792 try testExpect(H, 0, "", 0x2d06800538d394c2);
......@@ -820,7 +818,6 @@ test "xxhash3" {
820818}
821819
822820test "xxhash3 smhasher" {
823 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
824821 const Test = struct {
825822 fn do() !void {
826823 try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405);
......@@ -832,7 +829,6 @@ test "xxhash3 smhasher" {
832829}
833830
834831test "xxhash3 iterative api" {
835 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
836832 const Test = struct {
837833 fn do() !void {
838834 try verify.iterativeApi(XxHash3);
lib/std/hash_map.zig+1-1
......@@ -1518,7 +1518,7 @@ fn Custom(
15181518 self.available = 0;
15191519 }
15201520
1521 /// This function is used in the debugger pretty formatters in tools/ to fetch the
1521 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
15221522 /// header type to facilitate fancy debug printing for this type.
15231523 fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void {
15241524 _ = self;
lib/std/http/test.zig+1-20
......@@ -1,5 +1,4 @@
11const builtin = @import("builtin");
2const native_endian = builtin.cpu.arch.endian();
32
43const std = @import("std");
54const http = std.http;
......@@ -34,7 +33,6 @@ test "content length reader state update" {
3433}
3534
3635test "trailers" {
37 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
3836 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
3937
4038 const io = std.testing.io;
......@@ -121,7 +119,6 @@ test "trailers" {
121119}
122120
123121test "HTTP server handles a chunked transfer coding request" {
124 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
125122 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
126123
127124 const io = std.testing.io;
......@@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" {
190187}
191188
192189test "echo content server" {
193 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
194190 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
195191
196192 const io = std.testing.io;
......@@ -281,12 +277,11 @@ test "echo content server" {
281277}
282278
283279test "Server.Request.respondStreaming non-chunked, unknown content-length" {
284 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
285280 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
286281
287282 const io = std.testing.io;
288283
289 if (builtin.os.tag == .windows) {
284 if (builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) {
290285 // https://github.com/ziglang/zig/issues/21457
291286 return error.SkipZigTest;
292287 }
......@@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" {
360355}
361356
362357test "receiving arbitrary http headers from the client" {
363 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
364358 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
365359
366360 const io = std.testing.io;
......@@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" {
426420}
427421
428422test "general client/server API coverage" {
429 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
430423 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
431424
432425 const io = std.testing.io;
433426
434 if (builtin.os.tag == .windows) {
435 // This test was never passing on Windows.
436 return error.SkipZigTest;
437 }
438
439427 const test_server = try createTestServer(io, struct {
440428 fn run(test_server: *TestServer) anyerror!void {
441429 const net_server = &test_server.net_server;
......@@ -922,7 +910,6 @@ test "general client/server API coverage" {
922910}
923911
924912test "Server streams both reading and writing" {
925 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
926913 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
927914
928915 const io = std.testing.io;
......@@ -1162,10 +1149,6 @@ const TestServer = struct {
11621149
11631150fn createTestServer(io: Io, S: type) !*TestServer {
11641151 if (builtin.single_threaded) return error.SkipZigTest;
1165 if (builtin.zig_backend == .stage2_llvm and native_endian == .big) {
1166 // https://github.com/ziglang/zig/issues/13782
1167 return error.SkipZigTest;
1168 }
11691152
11701153 const address = try net.IpAddress.parse("127.0.0.1", 0);
11711154
......@@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer {
11921175}
11931176
11941177test "redirect to different connection" {
1195 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
11961178 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
11971179
11981180 const io = std.testing.io;
......@@ -1280,7 +1262,6 @@ test "redirect to different connection" {
12801262}
12811263
12821264test "boot failed connections from the pool" {
1283 if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257
12841265 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
12851266
12861267 const io = std.testing.io;
lib/std/lang.zig+1
......@@ -214,6 +214,7 @@ pub const CallingConvention = union(enum(u8)) {
214214 // Calling conventions for the `x86` architecture.
215215 x86_sysv: X86RegparmOptions,
216216 x86_win: X86RegparmOptions,
217 x86_mingw: X86RegparmOptions,
217218 x86_stdcall: X86RegparmOptions,
218219 x86_fastcall: CommonOptions,
219220 x86_thiscall: CommonOptions,
lib/std/math.zig+5-4
......@@ -75,7 +75,7 @@ pub const snan = float.snan;
7575///
7676/// NaN values are never considered equal to any value.
7777pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
78 assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
78 comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
7979 assert(tolerance >= 0);
8080
8181 // Fast path for equal values (and signed zeros and infinites).
......@@ -103,7 +103,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
103103///
104104/// NaN values are never considered equal to any value.
105105pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {
106 assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
106 comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float);
107107 assert(tolerance > 0);
108108
109109 // Fast path for equal values (and signed zeros and infinites).
......@@ -461,7 +461,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {
461461 }
462462}
463463test wrap {
464 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) {
464 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) {
465465 // https://codeberg.org/ziglang/zig/issues/35520
466466 return error.SkipZigTest;
467467 }
......@@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {
13851385}
13861386
13871387test lerp {
1388 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884
1388 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1389 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isX86()) return error.SkipZigTest;
13891390 if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884
13901391
13911392 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5));
lib/std/math/acos.zig-4
......@@ -337,8 +337,6 @@ fn acosBinary128(x: f128) f128 {
337337}
338338
339339test "acosBinary16.special" {
340 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
341
342340 try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0));
343341 try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1));
344342 try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0));
......@@ -350,8 +348,6 @@ test "acosBinary16.special" {
350348}
351349
352350test "acosBinary16" {
353 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
354
355351 try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0));
356352 try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0));
357353 try testing.expectApproxEqAbs(0x1.b7cp0, acosBinary16(-0x1.2c4p-3), math.floatEpsAt(f16, 0x1.b7cp0));
lib/std/math/asin.zig-4
......@@ -326,8 +326,6 @@ fn asinBinary128(x: f128) f128 {
326326}
327327
328328test "asinBinary16.special" {
329 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
330
331329 try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0));
332330 try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0));
333331 try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0));
......@@ -340,8 +338,6 @@ test "asinBinary16.special" {
340338}
341339
342340test "asinBinary16" {
343 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
344
345341 try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6));
346342 try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0));
347343 try testing.expectApproxEqAbs(-0x1.eep-1, asinBinary16(-0x1.a4cp-1), math.floatEpsAt(f16, -0x1.eep-1));
lib/std/math/atan.zig-4
......@@ -481,8 +481,6 @@ fn atanBinary128(x: f128) f128 {
481481}
482482
483483test "atanBinary16.special" {
484 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
485
486484 try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0));
487485 try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0));
488486 try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1));
......@@ -493,8 +491,6 @@ test "atanBinary16.special" {
493491}
494492
495493test "atanBinary16" {
496 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
497
498494 try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2));
499495 try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0));
500496 try testing.expectApproxEqAbs(-0x1.11cp0, atanBinary16(-0x1.d2cp0), math.floatEpsAt(f16, -0x1.11cp0));
lib/std/math/atan2.zig+4-4
......@@ -252,8 +252,8 @@ test "atan2_32.special" {
252252
253253 try expect(math.isNan(atan2_32(1.0, math.nan(f32))));
254254 try expect(math.isNan(atan2_32(math.nan(f32), 1.0)));
255 try expect(atan2_32(0.0, 5.0) == 0.0);
256 try expect(atan2_32(-0.0, 5.0) == -0.0);
255 try expect(math.isPositiveZero(atan2_32(0.0, 5.0)));
256 try expect(math.isNegativeZero(atan2_32(-0.0, 5.0)));
257257 try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
258258 //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?
259259 try expect(math.approxEqAbs(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));
......@@ -276,8 +276,8 @@ test "atan2_64.special" {
276276
277277 try expect(math.isNan(atan2_64(1.0, math.nan(f64))));
278278 try expect(math.isNan(atan2_64(math.nan(f64), 1.0)));
279 try expect(atan2_64(0.0, 5.0) == 0.0);
280 try expect(atan2_64(-0.0, 5.0) == -0.0);
279 try expect(math.isPositiveZero(atan2_64(0.0, 5.0)));
280 try expect(math.isNegativeZero(atan2_64(-0.0, 5.0)));
281281 try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
282282 //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero?
283283 try expect(math.approxEqAbs(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));
lib/std/math/big/int_test.zig+1-38
......@@ -1,5 +1,4 @@
11const std = @import("../../std.zig");
2const builtin = @import("builtin");
32const mem = std.mem;
43const testing = std.testing;
54const Managed = std.math.big.int.Managed;
......@@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void {
276275 try expectNormalized(1 << 10, res.toConst());
277276}
278277test setFloat {
279 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
280
281278 try setFloat(f16);
282279 try setFloat(f32);
283280 try setFloat(f64);
......@@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void {
484481 );
485482}
486483test toFloat {
487 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
488484 try toFloat(f16);
489485 try toFloat(f32);
490486 try toFloat(f64);
......@@ -1391,8 +1387,6 @@ test "mul multi-single" {
13911387}
13921388
13931389test "mul multi-multi" {
1394 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1395
13961390 var op1: u256 = 0x998888efefefefefefefef;
13971391 var op2: u256 = 0x333000abababababababab;
13981392 _ = .{ &op1, &op2 };
......@@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" {
15141508}
15151509
15161510test "mulWrap multi-multi unsigned" {
1517 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1518
15191511 var op1: u256 = 0x998888efefefefefefefef;
15201512 var op2: u256 = 0x333000abababababababab;
15211513 _ = .{ &op1, &op2 };
......@@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" {
15331525}
15341526
15351527test "mulWrap multi-multi signed" {
1536 switch (builtin.zig_backend) {
1537 .stage2_c => return error.SkipZigTest,
1538 else => {},
1539 }
1540
15411528 var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1);
15421529 defer a.deinit();
15431530 var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb));
......@@ -1744,8 +1731,6 @@ test "div q=0 alias" {
17441731}
17451732
17461733test "div multi-multi q < r" {
1747 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1748
17491734 const op1 = 0x1ffffffff0078f432;
17501735 const op2 = 0x1ffffffff01000000;
17511736 var a = try Managed.initSet(testing.allocator, op1);
......@@ -2166,8 +2151,6 @@ test "div ceil multi-limb" {
21662151}
21672152
21682153test "div multi-multi with rem" {
2169 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2170
21712154 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999);
21722155 defer a.deinit();
21732156 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
......@@ -2184,8 +2167,6 @@ test "div multi-multi with rem" {
21842167}
21852168
21862169test "div multi-multi no rem" {
2187 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2188
21892170 var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361);
21902171 defer a.deinit();
21912172 var b = try Managed.initSet(testing.allocator, 0x99990000111122223333);
......@@ -2202,8 +2183,6 @@ test "div multi-multi no rem" {
22022183}
22032184
22042185test "div multi-multi (2 branch)" {
2205 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2206
22072186 var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111);
22082187 defer a.deinit();
22092188 var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333);
......@@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" {
22202199}
22212200
22222201test "div multi-multi (3.1/3.3 branch)" {
2223 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2224
22252202 var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111);
22262203 defer a.deinit();
22272204 var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171);
......@@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" {
22382215}
22392216
22402217test "div multi-single zero-limb trailing" {
2241 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2242
22432218 var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000);
22442219 defer a.deinit();
22452220 var b = try Managed.initSet(testing.allocator, 0x10000000000000000);
......@@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" {
22582233}
22592234
22602235test "div multi-multi zero-limb trailing (with rem)" {
2261 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2262
22632236 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
22642237 defer a.deinit();
22652238 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
......@@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" {
22792252}
22802253
22812254test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" {
2282 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2283
22842255 var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000);
22852256 defer a.deinit();
22862257 var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000);
......@@ -2300,8 +2271,6 @@ test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count
23002271}
23012272
23022273test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" {
2303 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2304
23052274 var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000);
23062275 defer a.deinit();
23072276 var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000);
......@@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" {
28322801}
28332802
28342803test "bitNotWrap more than two limbs" {
2835 // This test requires int sizes greater than 128 bits.
2836 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2838
28392804 var a = try Managed.initSet(testing.allocator, maxInt(Limb));
28402805 defer a.deinit();
28412806
......@@ -3179,8 +3144,6 @@ test "gcd non-one large" {
31793144}
31803145
31813146test "gcd large multi-limb result" {
3182 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3183
31843147 var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678);
31853148 defer a.deinit();
31863149 var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567);
......@@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" {
34313394 var buffer1 = try testing.allocator.alloc(u8, 64);
34323395 defer testing.allocator.free(buffer1);
34333396
3434 const endians = [_]std.builtin.Endian{ .little, .big };
3397 const endians = [_]std.lang.Endian{ .little, .big };
34353398 const abi_size = 64;
34363399
34373400 for (endians) |endian| {
lib/std/math/gamma.zig-2
......@@ -263,8 +263,6 @@ test gamma {
263263}
264264
265265test "gamma.special" {
266 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
267
268266 inline for (&.{ f32, f64 }) |T| {
269267 try expect(std.math.isNan(gamma(T, -std.math.nan(T))));
270268 try expect(std.math.isNan(gamma(T, std.math.nan(T))));
lib/std/math/hypot.zig-9
......@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
21const std = @import("../std.zig");
32const math = std.math;
43const expect = std.testing.expect;
......@@ -93,14 +92,10 @@ const hypot_test_cases = .{
9392};
9493
9594test hypot {
96 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
9795 try expect(hypot(0.3, 0.4) == 0.5);
9896}
9997
10098test "hypot.correct" {
101 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
102 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
103
10499 inline for (.{ f16, f32, f64, f128 }) |T| {
105100 inline for (hypot_test_cases) |v| {
106101 const a: T, const b: T, const c: T = v;
......@@ -110,9 +105,6 @@ test "hypot.correct" {
110105}
111106
112107test "hypot.precise" {
113 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
114 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
115
116108 inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp
117109 inline for (hypot_test_cases) |v| {
118110 const a: T, const b: T, const c: T = v;
......@@ -122,7 +114,6 @@ test "hypot.precise" {
122114}
123115
124116test "hypot.special" {
125 if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869
126117 @setEvalBranchQuota(2000);
127118 inline for (.{ f16, f32, f64, f128 }) |T| {
128119 try expect(math.isNan(hypot(nan(T), 0.0)));
lib/std/math/isnan.zig+1-7
......@@ -27,13 +27,6 @@ test isNan {
2727}
2828
2929test isSignalNan {
30 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
31
32 if (builtin.os.tag == .windows) {
33 // https://codeberg.org/ziglang/zig/issues/35519
34 return error.SkipZigTest;
35 }
36
3730 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
3831 // TODO: Signalling NaN values get converted to quiet NaN values in
3932 // some cases where they shouldn't such that this can fail.
......@@ -43,6 +36,7 @@ test isSignalNan {
4336 builtin.cpu.arch != .hexagon and
4437 !builtin.cpu.arch.isMIPS32() and
4538 !builtin.cpu.arch.isPowerPC() and
39 !(builtin.cpu.arch.isX86() and builtin.os.tag == .windows and builtin.abi == .msvc) and // https://codeberg.org/ziglang/zig/issues/35519
4640 builtin.zig_backend != .stage2_c)
4741 {
4842 try expect(isSignalNan(math.snan(T)));
lib/std/math/log10.zig-5
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32const testing = std.testing;
43
54/// Returns the base-10 logarithm of x.
......@@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 {
135134}
136135
137136test log10_int {
138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
141
142137 inline for (
143138 .{ u8, u16, u32, u64, u128, u256, u512 },
144139 .{ 2, 4, 9, 19, 38, 77, 154 },
lib/std/math/modf.zig-4
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32const math = std.math;
43const expect = std.testing.expect;
54const expectEqual = std.testing.expectEqual;
......@@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type {
8584 try expectApproxEqAbs(expected_c, r.fpart, epsilon);
8685 }
8786 test "vector" {
88 if (builtin.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return error.SkipZigTest;
89 if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194256
90
9187 const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 };
9288
9389 inline for (widths) |len| {
lib/std/math/signbit.zig+1
......@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
12const std = @import("../std.zig");
23const math = std.math;
34const expect = std.testing.expect;
lib/std/mem.zig+35-53
......@@ -4780,62 +4780,47 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
47804780pub fn doNotOptimizeAway(val: anytype) void {
47814781 if (@inComptime()) return;
47824782
4783 if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) {
4784 _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct {
4785 var escape: *const anyopaque = undefined;
4786 }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded")
4787 return;
4788 }
4789
47834790 const max_gp_register_bits = @bitSizeOf(c_long);
4784 const t = @typeInfo(@TypeOf(val));
4785 switch (t) {
4791 switch (@typeInfo(@TypeOf(val))) {
47864792 .void, .null, .comptime_int, .comptime_float => return,
47874793 .@"enum" => doNotOptimizeAway(@backingInt(val)),
47884794 .bool => doNotOptimizeAway(@intFromBool(val)),
4789 .int => {
4790 const bits = t.int.bits;
4791 if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) {
4792 const val2 = @as(
4793 @Int(t.int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))),
4794 val,
4795 );
4796 asm volatile (""
4797 :
4798 : [_] "r" (val2),
4799 );
4800 } else doNotOptimizeAway(&val);
4801 },
4802 .float => {
4803 if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) {
4804 asm volatile (""
4805 :
4806 : [_] "rm" (val),
4807 );
4808 } else doNotOptimizeAway(&val);
4809 },
4810 .pointer => {
4811 if (builtin.zig_backend == .stage2_c) {
4812 doNotOptimizeAwayC(val);
4813 } else {
4814 asm volatile (""
4815 :
4816 : [_] "m" (val),
4817 : .{ .memory = true });
4818 }
4819 },
4820 .array => {
4821 if (t.array.len * @sizeOf(t.array.child) <= 64) {
4822 for (val) |v| doNotOptimizeAway(v);
4823 } else doNotOptimizeAway(&val);
4795 .int => |int| if (int.bits <= max_gp_register_bits) {
4796 const val2 = @as(
4797 @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))),
4798 val,
4799 );
4800 asm volatile (""
4801 :
4802 : [_] "r" (val2),
4803 );
4804 } else doNotOptimizeAway(&val),
4805 .float => |float| switch (float.bits) {
4806 else => comptime unreachable,
4807 16, 80, 128 => doNotOptimizeAway(&val),
4808 32, 64 => asm volatile (""
4809 :
4810 : [_] "rm" (val),
4811 ),
48244812 },
4813 .pointer => asm volatile (""
4814 :
4815 : [_] "m" (val),
4816 : .{ .memory = true }),
4817 .array => |array| if (array.len * @sizeOf(array.child) <= 64) {
4818 for (val) |v| doNotOptimizeAway(v);
4819 } else doNotOptimizeAway(&val),
48254820 else => doNotOptimizeAway(&val),
48264821 }
48274822}
48284823
4829/// .stage2_c doesn't support asm blocks yet, so use volatile stores instead
4830var deopt_target: if (builtin.zig_backend == .stage2_c) u8 else void = undefined;
4831fn doNotOptimizeAwayC(ptr: anytype) void {
4832 const dest = @as(*volatile u8, @ptrCast(&deopt_target));
4833 for (asBytes(ptr)) |b| {
4834 dest.* = b;
4835 }
4836 dest.* = 0;
4837}
4838
48394824test doNotOptimizeAway {
48404825 comptime doNotOptimizeAway("test");
48414826
......@@ -4994,12 +4979,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice
49944979}
49954980
49964981test "read/write(Var)PackedInt" {
4997 switch (builtin.cpu.arch) {
4998 // This test generates too much code to execute on WASI.
4999 // LLVM backend fails with "too many locals: locals exceed maximum"
5000 .wasm32, .wasm64 => return error.SkipZigTest,
5001 else => {},
5002 }
4982 // This test generates too much code to execute on WASI.
4983 // LLVM backend fails with "too many locals: locals exceed maximum"
4984 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
50034985
50044986 const foreign_endian: Endian = if (native_endian == .big) .little else .big;
50054987 const expect = std.testing.expect;
lib/std/multi_array_list.zig+2-2
......@@ -163,7 +163,7 @@ pub fn MultiArrayList(comptime T: type) type {
163163 };
164164 }
165165
166 /// This function is used in the debugger pretty formatters in tools/ to fetch the
166 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
167167 /// child field order and entry type to facilitate fancy debug printing for this type.
168168 fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void {
169169 _ = self;
......@@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type {
681681 }
682682 break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs);
683683 };
684 /// This function is used in the debugger pretty formatters in tools/ to fetch the
684 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
685685 /// child field order and entry type to facilitate fancy debug printing for this type.
686686 fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void {
687687 _ = self;
lib/std/os/linux/IoUring/test.zig-7
......@@ -1836,8 +1836,6 @@ test "accept/connect/send_zc/recv" {
18361836}
18371837
18381838test "accept_direct" {
1839 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30854
1840
18411839 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
18421840
18431841 var ring = IoUring.init(1, 0) catch |err| switch (err) {
......@@ -1925,11 +1923,6 @@ test "accept_direct" {
19251923test "accept_multishot_direct" {
19261924 try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
19271925
1928 if (builtin.cpu.arch == .riscv64) {
1929 // https://github.com/ziglang/zig/issues/25734
1930 return error.SkipZigTest;
1931 }
1932
19331926 var ring = IoUring.init(1, 0) catch |err| switch (err) {
19341927 error.SystemOutdated => return error.SkipZigTest,
19351928 error.PermissionDenied => return error.SkipZigTest,
lib/std/os/linux/aarch64.zig+1-1
......@@ -154,7 +154,7 @@ pub const restore = restore_rt;
154154pub fn restore_rt() callconv(.naked) noreturn {
155155 switch (builtin.zig_backend) {
156156 .stage2_c => asm volatile (
157 \\ mov x8, %[number]
157 \\ mov w8, %[number]
158158 \\ svc #0
159159 :
160160 : [number] "i" (@backingInt(SYS.rt_sigreturn)),
lib/std/os/linux/s390x.zig+26-10
......@@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 {
174174}
175175
176176pub fn restore() callconv(.naked) noreturn {
177 asm volatile (
178 \\svc 0
179 :
180 : [number] "{r1}" (@backingInt(SYS.sigreturn)),
181 );
177 switch (builtin.zig_backend) {
178 .stage2_c => asm volatile (
179 \\lghi %%r1, %[number]
180 \\svc 0
181 :
182 : [number] "K" (@backingInt(SYS.sigreturn)),
183 ),
184 else => asm volatile (
185 \\svc 0
186 :
187 : [number] "{r1}" (@backingInt(SYS.sigreturn)),
188 ),
189 }
182190}
183191
184192pub fn restore_rt() callconv(.naked) noreturn {
185 asm volatile (
186 \\svc 0
187 :
188 : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)),
189 );
193 switch (builtin.zig_backend) {
194 .stage2_c => asm volatile (
195 \\lghi %%r1, %[number]
196 \\svc 0
197 :
198 : [number] "K" (@backingInt(SYS.rt_sigreturn)),
199 ),
200 else => asm volatile (
201 \\svc 0
202 :
203 : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)),
204 ),
205 }
190206}
191207
192208pub const time_t = i64;
lib/std/testing/Smith.zig+1-1
......@@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) {
708708}
709709
710710test value {
711 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO
711 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
712712
713713 const S = struct {
714714 v: void = {},
lib/std/zig/llvm/Builder.zig+1307-471
......@@ -17,7 +17,7 @@ gpa: Allocator,
1717strip: bool,
1818
1919source_filename: String,
20data_layout: String,
20data_layout: DataLayout,
2121target_triple: String,
2222module_asm: std.ArrayList(u8),
2323
......@@ -87,6 +87,455 @@ pub const Options = struct {
8787 triple: []const u8 = &.{},
8888};
8989
90pub const DataLayout = struct {
91 endian: ?std.lang.Endian,
92 int_specs: PrimitiveSpec.Map,
93 float_specs: PrimitiveSpec.Map,
94 vector_specs: PrimitiveSpec.Map,
95 pointer_specs: PointerSpec.Map,
96 string_repr: String,
97
98 const PrimitiveSpec = packed struct(u32) {
99 bit_width: BitWidth,
100 abi_align: Alignment,
101 pref_align: Alignment,
102
103 const BitWidth = u20;
104
105 const Map = std.array_hash_map.Custom(PrimitiveSpec, void, Context, false);
106
107 const Context = struct {
108 pub fn hash(_: Context, spec: PrimitiveSpec) u32 {
109 return std.hash.int(spec.bit_width);
110 }
111
112 pub fn eql(_: Context, lhs_spec: PrimitiveSpec, rhs_spec: PrimitiveSpec, _: usize) bool {
113 return lhs_spec.bit_width == rhs_spec.bit_width;
114 }
115 };
116 };
117
118 const PointerSpec = struct {
119 bit_width: BitWidth,
120 index_bit_width: BitWidth,
121 flags: packed struct(u32) {
122 abi_align: Alignment,
123 pref_align: Alignment,
124 has_unstable_repr: bool,
125 has_external_state: bool,
126 null_ptr_repr: NullPtrRepr,
127 unused: u17 = 0,
128 },
129 addr_space_name: String,
130
131 const BitWidth = u32;
132
133 const NullPtrRepr = enum(u1) { all_zeros, all_ones };
134
135 const Map = std.array_hash_map.Auto(AddrSpace, PointerSpec);
136 };
137
138 pub fn stringForTarget(target: *const std.Target) []const u8 {
139 // These data layouts should match Clang.
140 return switch (target.cpu.arch) {
141 .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32",
142 .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32",
143 .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048",
144 .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64",
145 .aarch64 => if (target.ofmt == .macho)
146 if (target.os.tag == .windows or target.os.tag == .uefi)
147 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
148 else if (target.abi == .ilp32)
149 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
150 else
151 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
152 else if (target.os.tag == .windows or target.os.tag == .uefi)
153 "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32"
154 else
155 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
156 .aarch64_be => "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
157 .arm => if (target.ofmt == .macho)
158 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
159 else
160 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
161 .armeb, .thumbeb => if (target.ofmt == .macho)
162 "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
163 else
164 "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
165 .thumb => if (target.ofmt == .macho)
166 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
167 else if (target.os.tag == .windows or target.os.tag == .uefi)
168 "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
169 else
170 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
171 .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8",
172 .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
173 .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
174 .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
175 .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
176 .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
177 .mips64 => switch (target.abi) {
178 .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
179 else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
180 },
181 .mips64el => switch (target.abi) {
182 .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
183 else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
184 },
185 .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
186 .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32",
187 .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
188 .powerpc64 => switch (target.os.tag) {
189 .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512",
190 .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64",
191 else => "E-m:e-Fn32-i64:64-i128:128-n32:64",
192 },
193 .powerpc64le => if (target.os.tag == .linux)
194 "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
195 else
196 "e-m:e-Fn32-i64:64-i128:128-n32:64",
197 .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
198 .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
199 .amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9",
200 .riscv32 => if (target.cpu.has(.riscv, .e))
201 "e-m:e-p:32:32-i64:64-n32-S32"
202 else
203 "e-m:e-p:32:32-i64:64-n32-S128",
204 .riscv32be => if (target.cpu.has(.riscv, .e))
205 "E-m:e-p:32:32-i64:64-n32-S32"
206 else
207 "E-m:e-p:32:32-i64:64-n32-S128",
208 .riscv64 => if (target.cpu.has(.riscv, .e))
209 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
210 else
211 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
212 .riscv64be => if (target.cpu.has(.riscv, .e))
213 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
214 else
215 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
216 .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64",
217 .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128",
218 .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
219 .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) {
220 .gnu => if (target.ofmt == .coff)
221 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
222 else
223 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
224 else => blk: {
225 const msvc = switch (target.abi) {
226 .none, .msvc => true,
227 else => false,
228 };
229
230 break :blk if (target.ofmt == .coff)
231 if (msvc)
232 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
233 else
234 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
235 else if (msvc)
236 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
237 else
238 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32";
239 },
240 } else if (target.ofmt == .macho)
241 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128"
242 else
243 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
244 .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
245 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
246 else switch (target.abi) {
247 .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
248 else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff)
249 "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
250 else
251 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
252 },
253 .spirv32 => switch (target.os.tag) {
254 .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
255 else => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
256 },
257 .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
258 .wasm32 => if (target.os.tag == .emscripten)
259 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20"
260 else
261 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
262 .wasm64 => if (target.os.tag == .emscripten)
263 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20"
264 else
265 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
266 .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64",
267 .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32",
268 .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128",
269 .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
270 .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32",
271
272 .alpha,
273 .arceb,
274 .ez80,
275 .hppa,
276 .hppa64,
277 .kalimba,
278 .kvx,
279 .m88k,
280 .microblaze,
281 .microblazeel,
282 .or1k,
283 .propeller,
284 .sh,
285 .sheb,
286 .x86_16,
287 .xtensaeb,
288 => unreachable,
289 };
290 }
291
292 const default_int_specs: []const PrimitiveSpec = &.{
293 .{ .bit_width = 8, .abi_align = .fromByteUnits(1), .pref_align = .fromByteUnits(1) }, // i8:8:8
294 .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // i16:16:16
295 .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // i32:32:32
296 .{ .bit_width = 64, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(8) }, // i64:32:64
297 };
298 const default_float_specs: []const PrimitiveSpec = &.{
299 .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // f16:16:16
300 .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // f32:32:32
301 .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // f64:64:64
302 .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // f128:128:128
303 };
304 const default_vector_specs: []const PrimitiveSpec = &.{
305 .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // v64:64:64
306 .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // v128:128:128
307 };
308
309 pub fn parseString(string_repr: String, builder: *Builder) Allocator.Error!DataLayout {
310 const gpa = builder.gpa;
311
312 var int_specs: PrimitiveSpec.Map = .empty;
313 defer int_specs.deinit(gpa);
314 var float_specs: PrimitiveSpec.Map = .empty;
315 defer float_specs.deinit(gpa);
316 var vector_specs: PrimitiveSpec.Map = .empty;
317 defer vector_specs.deinit(gpa);
318 var pointer_specs: PointerSpec.Map = .empty;
319 defer pointer_specs.deinit(gpa);
320 var non_integral_addr_spaces: std.ArrayList(AddrSpace) = .empty;
321 defer non_integral_addr_spaces.deinit(gpa);
322
323 try int_specs.ensureTotalCapacity(gpa, default_int_specs.len);
324 for (default_int_specs) |int_spec| int_specs.putAssumeCapacityNoClobber(int_spec, {});
325 try float_specs.ensureTotalCapacity(gpa, default_float_specs.len);
326 for (default_float_specs) |float_spec| float_specs.putAssumeCapacityNoClobber(float_spec, {});
327 try vector_specs.ensureTotalCapacity(gpa, default_vector_specs.len);
328 for (default_vector_specs) |vector_spec| vector_specs.putAssumeCapacityNoClobber(vector_spec, {});
329 try pointer_specs.putNoClobber(gpa, .default, comptime .{
330 .bit_width = 64,
331 .index_bit_width = 64,
332 .flags = .{
333 .abi_align = .fromByteUnits(8),
334 .pref_align = .fromByteUnits(8),
335 .has_unstable_repr = false,
336 .has_external_state = false,
337 .null_ptr_repr = .all_zeros,
338 },
339 .addr_space_name = .none,
340 });
341
342 var endian: ?std.lang.Endian = null;
343 var spec_it = std.mem.splitScalar(u8, string_repr.slice(builder).?, '-');
344 while (spec_it.next()) |spec| switch (spec[0]) {
345 else => {},
346 'E' => {
347 assert(spec.len == 1);
348 assert(endian == null);
349 endian = .big;
350 },
351 'e' => {
352 assert(spec.len == 1);
353 assert(endian == null);
354 endian = .little;
355 },
356 'p' => {
357 var field_it = std.mem.splitScalar(u8, spec[1..], ':');
358
359 const first = field_it.first();
360 var has_unstable_repr = false;
361 var has_external_state = false;
362 var null_ptr_repr: ?PointerSpec.NullPtrRepr = null;
363 var addr_space_name: String = .none;
364 const addr_space = for (first, 0..) |flag, as_start| switch (flag) {
365 'u' => has_unstable_repr = true,
366 'e' => has_external_state = true,
367 'z' => {
368 assert(null_ptr_repr == null);
369 null_ptr_repr = .all_zeros;
370 },
371 'o' => {
372 assert(null_ptr_repr == null);
373 null_ptr_repr = .all_ones;
374 },
375 else => {
376 if (first[first.len - ")".len] != ')') break first[as_start..];
377 const name_start = std.mem.findScalarPos(u8, first, as_start, '(').?;
378 addr_space_name = try builder.string(first[name_start + "(".len .. first.len - ")".len]);
379 break first[as_start..name_start];
380 },
381 } else first[first.len..];
382 const bit_width = std.fmt.parseInt(PointerSpec.BitWidth, field_it.next().?, 10) catch unreachable;
383 const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable);
384 const pref_align: Alignment = if (field_it.next()) |pref_align|
385 .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable)
386 else
387 abi_align;
388 const index_bit_width = if (field_it.next()) |index_bit_width|
389 std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable
390 else
391 bit_width;
392 assert(field_it.peek() == null);
393
394 try pointer_specs.put(gpa, switch (addr_space.len) {
395 0 => .default,
396 else => @fromBackingInt(std.fmt.parseInt(u24, addr_space, 10) catch unreachable),
397 }, .{
398 .bit_width = bit_width,
399 .index_bit_width = index_bit_width,
400 .flags = .{
401 .abi_align = abi_align,
402 .pref_align = pref_align,
403 .has_unstable_repr = has_unstable_repr,
404 .has_external_state = has_external_state,
405 .null_ptr_repr = null_ptr_repr orelse .all_zeros,
406 },
407 .addr_space_name = addr_space_name,
408 });
409 },
410 'i', 'f', 'v' => |kind| {
411 if (std.mem.eql(u8, spec, "ve")) {
412 vector_specs.clearRetainingCapacity();
413 continue;
414 }
415 var field_it = std.mem.splitScalar(u8, spec[1..], ':');
416 const bit_width = std.fmt.parseInt(PrimitiveSpec.BitWidth, field_it.first(), 10) catch unreachable;
417 const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable);
418 const pref_align: Alignment = if (field_it.next()) |pref_align|
419 .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable)
420 else
421 abi_align;
422 assert(field_it.peek() == null);
423 const specs = switch (kind) {
424 else => unreachable,
425 'i' => &int_specs,
426 'f' => &float_specs,
427 'v' => &vector_specs,
428 };
429 try specs.put(gpa, .{ .bit_width = bit_width, .abi_align = abi_align, .pref_align = pref_align }, {});
430 },
431 'n' => {
432 var field_it = std.mem.splitScalar(u8, spec[1..], ':');
433 if (std.mem.eql(u8, field_it.first(), "i")) {
434 while (field_it.next()) |non_integral_addr_space| try non_integral_addr_spaces.append(
435 gpa,
436 @fromBackingInt(std.fmt.parseInt(u24, non_integral_addr_space, 10) catch unreachable),
437 );
438 } else {
439 field_it.reset();
440 while (field_it.next()) |native_bit_width| {
441 _ = std.fmt.parseInt(PrimitiveSpec.BitWidth, native_bit_width, 10) catch unreachable;
442 }
443 }
444 },
445 };
446
447 for (non_integral_addr_spaces.items) |non_integral_addr_space| {
448 const pointer_spec_gop = try pointer_specs.getOrPut(gpa, non_integral_addr_space);
449 if (!pointer_spec_gop.found_existing) pointer_spec_gop.value_ptr.* = pointer_specs.get(.default).?;
450 pointer_spec_gop.value_ptr.flags.has_unstable_repr = true;
451 pointer_spec_gop.value_ptr.flags.has_external_state = false;
452 }
453
454 {
455 const SortContext = struct {
456 specs: []const PrimitiveSpec,
457 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
458 return ctx.specs[lhs_index].bit_width < ctx.specs[rhs_index].bit_width;
459 }
460 };
461 int_specs.sortUnstable(SortContext{ .specs = int_specs.keys() });
462 float_specs.sortUnstable(SortContext{ .specs = float_specs.keys() });
463 vector_specs.sortUnstable(SortContext{ .specs = vector_specs.keys() });
464 }
465 {
466 const SortContext = struct {
467 addr_spaces: []const AddrSpace,
468 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
469 return @backingInt(ctx.addr_spaces[lhs_index]) < @backingInt(ctx.addr_spaces[rhs_index]);
470 }
471 };
472 pointer_specs.sortUnstable(SortContext{ .addr_spaces = pointer_specs.keys() });
473 assert(pointer_specs.keys()[0] == .default);
474 }
475
476 return .{
477 .endian = endian,
478 .int_specs = int_specs.move(),
479 .float_specs = float_specs.move(),
480 .vector_specs = vector_specs.move(),
481 .pointer_specs = pointer_specs.move(),
482 .string_repr = string_repr,
483 };
484 }
485
486 pub fn deinit(data_layout: *DataLayout, gpa: Allocator) void {
487 data_layout.int_specs.deinit(gpa);
488 data_layout.float_specs.deinit(gpa);
489 data_layout.vector_specs.deinit(gpa);
490 data_layout.pointer_specs.deinit(gpa);
491 }
492
493 pub fn getIntegerSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec {
494 const specs = data_layout.int_specs.keys();
495 return specs[
496 @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct {
497 fn order(ctx: PrimitiveSpec.BitWidth, spec: PrimitiveSpec) std.math.Order {
498 return std.math.order(ctx, spec.bit_width);
499 }
500 }.order), specs.len - 1)
501 ];
502 }
503
504 pub fn getFloatSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec {
505 if (data_layout.float_specs.getEntry(.{
506 .bit_width = bit_width,
507 .abi_align = .default,
508 .pref_align = .default,
509 })) |entry| return entry.key_ptr.*;
510 const default_align: Alignment = .fromByteUnits(
511 std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, bit_width / 8),
512 );
513 return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align };
514 }
515
516 pub fn getVectorSpec(
517 data_layout: *const DataLayout,
518 bit_width: PrimitiveSpec.BitWidth,
519 store_size: Type.Size,
520 ) PrimitiveSpec {
521 if (data_layout.float_specs.getEntry(.{
522 .bit_width = bit_width,
523 .abi_align = .default,
524 .pref_align = .default,
525 })) |entry| return entry.key_ptr.*;
526 const default_align: Alignment = .fromByteUnits(
527 std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, switch (store_size) {
528 .fixed, .scalable => |known_min| known_min,
529 }),
530 );
531 return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align };
532 }
533
534 pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec {
535 return data_layout.pointer_specs.get(addr_space) orelse data_layout.pointer_specs.values()[0];
536 }
537};
538
90539pub const String = enum(u32) {
91540 none = maxInt(u31),
92541 empty,
......@@ -142,8 +591,8 @@ pub const String = enum(u32) {
142591 }
143592
144593 fn fromIndex(index: ?usize) String {
145 return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) +
146 @backingInt(String.empty)))));
594 return @fromBackingInt(@as(u32, @intCast((index orelse return .none) +
595 @backingInt(String.empty))));
147596 }
148597
149598 fn toIndex(self: String) ?usize {
......@@ -489,7 +938,10 @@ pub const Type = enum(u32) {
489938 .double, .i64, .x86_mmx => 64,
490939 .x86_fp80, .i80 => 80,
491940 .fp128, .ppc_fp128, .i128 => 128,
492 .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"),
941 .ptr => @intCast(builder.data_layout.getPointerSpec(.default).bit_width),
942 .@"ptr addrspace(4)" => @intCast(
943 builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(4))).bit_width,
944 ),
493945 _ => {
494946 const item = builder.type_items.items[@backingInt(self)];
495947 return switch (item.tag) {
......@@ -498,7 +950,9 @@ pub const Type = enum(u32) {
498950 .vararg_function,
499951 => unreachable,
500952 .integer => @intCast(item.data),
501 .pointer => @panic("TODO: query data layout"),
953 .pointer => @intCast(
954 builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width,
955 ),
502956 .target => unreachable,
503957 .vector,
504958 .scalable_vector,
......@@ -931,12 +1385,74 @@ pub const Type = enum(u32) {
9311385 },
9321386 };
9331387 }
1388
1389 const Size = union(enum) { fixed: u64, scalable: u64 };
1390 pub fn bits(ty: Type, builder: *const Builder) Size {
1391 const item = builder.type_items.items[@backingInt(ty)];
1392 return switch (item.tag) {
1393 else => unreachable,
1394 .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) {
1395 else => unreachable,
1396 .label => .{ .fixed = builder.data_layout.getPointerSpec(.default).bit_width },
1397 .half, .bfloat => .{ .fixed = 16 },
1398 .float => .{ .fixed = 32 },
1399 .double => .{ .fixed = 64 },
1400 .ppc_fp128, .fp128 => .{ .fixed = 128 },
1401 .x86_amx => .{ .fixed = 8192 },
1402 .x86_fp80 => .{ .fixed = 80 },
1403 },
1404 .integer => .{ .fixed = item.data },
1405 .pointer => .{
1406 .fixed = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width,
1407 },
1408 };
1409 }
1410
1411 pub fn alignment(ty: Type, kind: enum { abi, pref }, builder: *const Builder) Alignment {
1412 const item = builder.type_items.items[@backingInt(ty)];
1413 switch (item.tag) {
1414 else => unreachable,
1415 .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) {
1416 else => unreachable,
1417 .label => {
1418 const spec = builder.data_layout.getPointerSpec(.default);
1419 return switch (kind) {
1420 .abi => spec.flags.abi_align,
1421 .pref => spec.flags.pref_align,
1422 };
1423 },
1424 .half, .bfloat, .float, .double, .ppc_fp128, .fp128, .x86_fp80 => {
1425 const spec = builder.data_layout.getFloatSpec(@intCast(ty.bits(builder).fixed));
1426 return switch (kind) {
1427 .abi => spec.abi_align,
1428 .pref => spec.pref_align,
1429 };
1430 },
1431 .x86_amx => return comptime .fromByteUnits(64),
1432 },
1433 .integer => {
1434 const spec = builder.data_layout.getIntegerSpec(@intCast(item.data));
1435 return switch (kind) {
1436 .abi => spec.abi_align,
1437 .pref => spec.pref_align,
1438 };
1439 },
1440 .pointer => {
1441 const spec = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data)));
1442 return switch (kind) {
1443 .abi => spec.flags.abi_align,
1444 .pref => spec.flags.pref_align,
1445 };
1446 },
1447 }
1448 }
9341449};
9351450
9361451pub const Attribute = union(Kind) {
9371452 // Parameter Attributes
9381453 zeroext,
9391454 signext,
1455 noext,
9401456 inreg,
9411457 byval: Type,
9421458 byref: Type,
......@@ -947,6 +1463,7 @@ pub const Attribute = union(Kind) {
9471463 @"align": Alignment.Lazy,
9481464 @"noalias",
9491465 nocapture,
1466 captures: Captures,
9501467 nofree,
9511468 nest,
9521469 returned,
......@@ -965,6 +1482,11 @@ pub const Attribute = union(Kind) {
9651482 readnone,
9661483 readonly,
9671484 writeonly,
1485 writable,
1486 initializes: []const [2]u64,
1487 dead_on_unwind,
1488 dead_on_return: ?u32,
1489 range: [2]Constant,
9681490
9691491 // Function Attributes
9701492 //alignstack: Alignment.Lazy,
......@@ -974,7 +1496,7 @@ pub const Attribute = union(Kind) {
9741496 builtin,
9751497 cold,
9761498 convergent,
977 disable_sanitizer_information,
1499 disable_sanitizer_instrumentation,
9781500 fn_ret_thunk_extern,
9791501 hot,
9801502 inlinehint,
......@@ -984,6 +1506,7 @@ pub const Attribute = union(Kind) {
9841506 naked,
9851507 nobuiltin,
9861508 nocallback,
1509 nodivergencesource,
9871510 noduplicate,
9881511 //nofree,
9891512 noimplicitfloat,
......@@ -1001,6 +1524,7 @@ pub const Attribute = union(Kind) {
10011524 nosanitize_bounds,
10021525 nosanitize_coverage,
10031526 null_pointer_is_valid,
1527 optdebug,
10041528 optforfuzzing,
10051529 optnone,
10061530 optsize,
......@@ -1012,23 +1536,23 @@ pub const Attribute = union(Kind) {
10121536 sanitize_thread,
10131537 sanitize_hwaddress,
10141538 sanitize_memtag,
1539 sanitize_realtime,
1540 sanitize_realtime_blocking,
1541 sanitize_alloc_token,
10151542 speculative_load_hardening,
10161543 speculatable,
10171544 ssp,
10181545 sspstrong,
10191546 sspreq,
10201547 strictfp,
1548 denormal_fpenv,
10211549 uwtable: UwTable,
10221550 nocf_check,
10231551 shadowcallstack,
10241552 mustprogress,
10251553 vscale_range: VScaleRange,
1026
1027 // Global Attributes
1028 no_sanitize_address,
1029 no_sanitize_hwaddress,
1030 //sanitize_memtag,
1031 sanitize_address_dyninit,
1554 nooutline,
1555 nocreateundeforpoison,
10321556
10331557 string: struct { kind: String, value: String },
10341558 none: noreturn,
......@@ -1045,100 +1569,11 @@ pub const Attribute = union(Kind) {
10451569 const storage = self.toStorage(builder);
10461570 if (storage.kind.toString()) |kind| return .{ .string = .{
10471571 .kind = kind,
1048 .value = @fromBackingInt(@intCast(storage.value)),
1572 .value = @fromBackingInt(storage.value),
10491573 } } else return switch (storage.kind) {
1050 inline .zeroext,
1051 .signext,
1052 .inreg,
1053 .byval,
1054 .byref,
1055 .preallocated,
1056 .inalloca,
1057 .sret,
1058 .elementtype,
1059 .@"align",
1060 .@"noalias",
1061 .nocapture,
1062 .nofree,
1063 .nest,
1064 .returned,
1065 .nonnull,
1066 .dereferenceable,
1067 .dereferenceable_or_null,
1068 .swiftself,
1069 .swiftasync,
1070 .swifterror,
1071 .immarg,
1072 .noundef,
1073 .nofpclass,
1074 .alignstack,
1075 .allocalign,
1076 .allocptr,
1077 .readnone,
1078 .readonly,
1079 .writeonly,
1080 //.alignstack,
1081 .allockind,
1082 .allocsize,
1083 .alwaysinline,
1084 .builtin,
1085 .cold,
1086 .convergent,
1087 .disable_sanitizer_information,
1088 .fn_ret_thunk_extern,
1089 .hot,
1090 .inlinehint,
1091 .jumptable,
1092 .memory,
1093 .minsize,
1094 .naked,
1095 .nobuiltin,
1096 .nocallback,
1097 .noduplicate,
1098 //.nofree,
1099 .noimplicitfloat,
1100 .@"noinline",
1101 .nomerge,
1102 .nonlazybind,
1103 .noprofile,
1104 .skipprofile,
1105 .noredzone,
1106 .noreturn,
1107 .norecurse,
1108 .willreturn,
1109 .nosync,
1110 .nounwind,
1111 .nosanitize_bounds,
1112 .nosanitize_coverage,
1113 .null_pointer_is_valid,
1114 .optforfuzzing,
1115 .optnone,
1116 .optsize,
1117 //.preallocated,
1118 .returns_twice,
1119 .safestack,
1120 .sanitize_address,
1121 .sanitize_memory,
1122 .sanitize_thread,
1123 .sanitize_hwaddress,
1124 .sanitize_memtag,
1125 .speculative_load_hardening,
1126 .speculatable,
1127 .ssp,
1128 .sspstrong,
1129 .sspreq,
1130 .strictfp,
1131 .uwtable,
1132 .nocf_check,
1133 .shadowcallstack,
1134 .mustprogress,
1135 .vscale_range,
1136 .no_sanitize_address,
1137 .no_sanitize_hwaddress,
1138 .sanitize_address_dyninit,
1139 => |kind| {
1574 inline else => |kind| {
11401575 const field_name, const field_type = comptime blk: {
1141 @setEvalBranchQuota(10_000);
1576 @setEvalBranchQuota(12_000);
11421577 const info = @typeInfo(Attribute).@"union";
11431578 for (info.field_names, info.field_types) |field_name, field_type| {
11441579 if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type };
......@@ -1149,14 +1584,17 @@ pub const Attribute = union(Kind) {
11491584 return @unionInit(Attribute, field_name, switch (field_type) {
11501585 void => {},
11511586 u32 => storage.value,
1152 Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)),
1153 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value),
1587 Alignment.Lazy, String, Type, UwTable => @fromBackingInt(storage.value),
1588 AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(storage.value),
11541589 else => @compileError("bad payload type: " ++ field_name ++ ": " ++
11551590 @typeName(field_type)),
11561591 });
11571592 },
1158 .string, .none => unreachable,
1159 _ => unreachable,
1593 .initializes,
1594 .dead_on_return,
1595 .range,
1596 => @panic("TODO"),
1597 .string, .none, _ => unreachable,
11601598 };
11611599 }
11621600
......@@ -1174,6 +1612,7 @@ pub const Attribute = union(Kind) {
11741612 switch (attribute) {
11751613 .zeroext,
11761614 .signext,
1615 .noext,
11771616 .inreg,
11781617 .@"noalias",
11791618 .nocapture,
......@@ -1191,11 +1630,13 @@ pub const Attribute = union(Kind) {
11911630 .readnone,
11921631 .readonly,
11931632 .writeonly,
1633 .writable,
1634 .dead_on_unwind,
11941635 .alwaysinline,
11951636 .builtin,
11961637 .cold,
11971638 .convergent,
1198 .disable_sanitizer_information,
1639 .disable_sanitizer_instrumentation,
11991640 .fn_ret_thunk_extern,
12001641 .hot,
12011642 .inlinehint,
......@@ -1204,6 +1645,7 @@ pub const Attribute = union(Kind) {
12041645 .naked,
12051646 .nobuiltin,
12061647 .nocallback,
1648 .nodivergencesource,
12071649 .noduplicate,
12081650 .noimplicitfloat,
12091651 .@"noinline",
......@@ -1220,6 +1662,7 @@ pub const Attribute = union(Kind) {
12201662 .nosanitize_bounds,
12211663 .nosanitize_coverage,
12221664 .null_pointer_is_valid,
1665 .optdebug,
12231666 .optforfuzzing,
12241667 .optnone,
12251668 .optsize,
......@@ -1230,18 +1673,21 @@ pub const Attribute = union(Kind) {
12301673 .sanitize_thread,
12311674 .sanitize_hwaddress,
12321675 .sanitize_memtag,
1676 .sanitize_realtime,
1677 .sanitize_realtime_blocking,
1678 .sanitize_alloc_token,
12331679 .speculative_load_hardening,
12341680 .speculatable,
12351681 .ssp,
12361682 .sspstrong,
12371683 .sspreq,
12381684 .strictfp,
1685 .denormal_fpenv,
12391686 .nocf_check,
12401687 .shadowcallstack,
12411688 .mustprogress,
1242 .no_sanitize_address,
1243 .no_sanitize_hwaddress,
1244 .sanitize_address_dyninit,
1689 .nooutline,
1690 .nocreateundeforpoison,
12451691 => try w.print(" {s}", .{@tagName(attribute)}),
12461692 .byval,
12471693 .byref,
......@@ -1254,6 +1700,45 @@ pub const Attribute = union(Kind) {
12541700 .dereferenceable,
12551701 .dereferenceable_or_null,
12561702 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
1703 .captures => |captures| {
1704 try w.print(" {s}(", .{@tagName(attribute)});
1705 var need_comma = false;
1706 if (captures == Captures.none) {
1707 if (need_comma) try w.writeAll(", ");
1708 try w.writeAll("none");
1709 need_comma = true;
1710 }
1711 inline for (@typeInfo(Captures).@"struct".field_names) |field_name| {
1712 if (comptime std.mem.eql(u8, field_name, "_")) continue;
1713 const components = @field(captures, field_name);
1714 if (components != Captures.Components.none) {
1715 if (!comptime std.mem.eql(u8, field_name, "other")) {
1716 if (need_comma) try w.writeAll(", ");
1717 try w.writeAll(field_name ++ ": ");
1718 need_comma = false;
1719 }
1720 if (components.address) {
1721 if (need_comma) try w.writeAll(", ");
1722 try w.writeAll("address");
1723 need_comma = true;
1724 } else if (components.address_is_null) {
1725 if (need_comma) try w.writeAll(", ");
1726 try w.writeAll("address_is_null");
1727 need_comma = true;
1728 }
1729 if (components.provenance) {
1730 if (need_comma) try w.writeAll(", ");
1731 try w.writeAll("provenance");
1732 need_comma = true;
1733 } else if (components.read_provenance) {
1734 if (need_comma) try w.writeAll(", ");
1735 try w.writeAll("read_provenance");
1736 need_comma = true;
1737 }
1738 }
1739 }
1740 try w.writeByte(')');
1741 },
12571742 .nofpclass => |fpclass| {
12581743 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
12591744 try w.print(" {s}(", .{@tagName(attribute)});
......@@ -1281,6 +1766,9 @@ pub const Attribute = union(Kind) {
12811766 try w.print("({d})", .{alignment_bytes});
12821767 }
12831768 },
1769 .initializes => @panic("TODO"),
1770 .dead_on_return => @panic("TODO"),
1771 .range => @panic("TODO"),
12841772 .allockind => |allockind| {
12851773 try w.print(" {t}(\"", .{attribute});
12861774 var any = false;
......@@ -1344,100 +1832,109 @@ pub const Attribute = union(Kind) {
13441832
13451833 pub const Kind = enum(u32) {
13461834 // Parameter Attributes
1347 zeroext = 34,
1348 signext = 24,
1349 inreg = 5,
1350 byval = 3,
1351 byref = 69,
1352 preallocated = 65,
1353 inalloca = 38,
1354 sret = 29, // TODO: ?
1355 elementtype = 77,
1356 @"align" = 1,
1357 @"noalias" = 9,
1358 nocapture = 11,
1359 nofree = 62,
1360 nest = 8,
1361 returned = 22,
1362 nonnull = 39,
1363 dereferenceable = 41,
1364 dereferenceable_or_null = 42,
1365 swiftself = 46,
1366 swiftasync = 75,
1367 swifterror = 47,
1368 immarg = 60,
1369 noundef = 68,
1370 nofpclass = 87,
1371 alignstack = 25,
1372 allocalign = 80,
1373 allocptr = 81,
1374 readnone = 20,
1375 readonly = 21,
1376 writeonly = 52,
1835 zeroext = @backingInt(ATTR_KIND.Z_EXT),
1836 signext = @backingInt(ATTR_KIND.S_EXT),
1837 noext = @backingInt(ATTR_KIND.NO_EXT),
1838 inreg = @backingInt(ATTR_KIND.IN_REG),
1839 byval = @backingInt(ATTR_KIND.BY_VAL),
1840 byref = @backingInt(ATTR_KIND.BYREF),
1841 preallocated = @backingInt(ATTR_KIND.PREALLOCATED),
1842 inalloca = @backingInt(ATTR_KIND.IN_ALLOCA),
1843 sret = @backingInt(ATTR_KIND.STRUCT_RET),
1844 elementtype = @backingInt(ATTR_KIND.ELEMENTTYPE),
1845 @"align" = @backingInt(ATTR_KIND.ALIGNMENT),
1846 @"noalias" = @backingInt(ATTR_KIND.NO_ALIAS),
1847 nocapture = @backingInt(ATTR_KIND.NO_CAPTURE),
1848 captures = @backingInt(ATTR_KIND.CAPTURES),
1849 nofree = @backingInt(ATTR_KIND.NOFREE),
1850 nest = @backingInt(ATTR_KIND.NEST),
1851 returned = @backingInt(ATTR_KIND.RETURNED),
1852 nonnull = @backingInt(ATTR_KIND.NON_NULL),
1853 dereferenceable = @backingInt(ATTR_KIND.DEREFERENCEABLE),
1854 dereferenceable_or_null = @backingInt(ATTR_KIND.DEREFERENCEABLE_OR_NULL),
1855 swiftself = @backingInt(ATTR_KIND.SWIFT_SELF),
1856 swiftasync = @backingInt(ATTR_KIND.SWIFT_ASYNC),
1857 swifterror = @backingInt(ATTR_KIND.SWIFT_ERROR),
1858 immarg = @backingInt(ATTR_KIND.IMMARG),
1859 noundef = @backingInt(ATTR_KIND.NOUNDEF),
1860 nofpclass = @backingInt(ATTR_KIND.NOFPCLASS),
1861 alignstack = @backingInt(ATTR_KIND.STACK_ALIGNMENT),
1862 allocalign = @backingInt(ATTR_KIND.ALLOC_ALIGN),
1863 allocptr = @backingInt(ATTR_KIND.ALLOCATED_POINTER),
1864 readnone = @backingInt(ATTR_KIND.READ_NONE),
1865 readonly = @backingInt(ATTR_KIND.READ_ONLY),
1866 writeonly = @backingInt(ATTR_KIND.WRITEONLY),
1867 writable = @backingInt(ATTR_KIND.WRITABLE),
1868 initializes = @backingInt(ATTR_KIND.INITIALIZES),
1869 dead_on_unwind = @backingInt(ATTR_KIND.DEAD_ON_UNWIND),
1870 dead_on_return = @backingInt(ATTR_KIND.DEAD_ON_RETURN),
1871 range = @backingInt(ATTR_KIND.RANGE),
13771872
13781873 // Function Attributes
1379 //alignstack,
1380 allockind = 82,
1381 allocsize = 51,
1382 alwaysinline = 2,
1383 builtin = 35,
1384 cold = 36,
1385 convergent = 43,
1386 disable_sanitizer_information = 78,
1387 fn_ret_thunk_extern = 84,
1388 hot = 72,
1389 inlinehint = 4,
1390 jumptable = 40,
1391 memory = 86,
1392 minsize = 6,
1393 naked = 7,
1394 nobuiltin = 10,
1395 nocallback = 71,
1396 noduplicate = 12,
1397 //nofree,
1398 noimplicitfloat = 13,
1399 @"noinline" = 14,
1400 nomerge = 66,
1401 nonlazybind = 15,
1402 noprofile = 73,
1403 skipprofile = 85,
1404 noredzone = 16,
1405 noreturn = 17,
1406 norecurse = 48,
1407 willreturn = 61,
1408 nosync = 63,
1409 nounwind = 18,
1410 nosanitize_bounds = 79,
1411 nosanitize_coverage = 76,
1412 null_pointer_is_valid = 67,
1413 optforfuzzing = 57,
1414 optnone = 37,
1415 optsize = 19,
1416 //preallocated,
1417 returns_twice = 23,
1418 safestack = 44,
1419 sanitize_address = 30,
1420 sanitize_memory = 32,
1421 sanitize_thread = 31,
1422 sanitize_hwaddress = 55,
1423 sanitize_memtag = 64,
1424 speculative_load_hardening = 59,
1425 speculatable = 53,
1426 ssp = 26,
1427 sspstrong = 28,
1428 sspreq = 27,
1429 strictfp = 54,
1430 uwtable = 33,
1431 nocf_check = 56,
1432 shadowcallstack = 58,
1433 mustprogress = 70,
1434 vscale_range = 74,
1435
1436 // Global Attributes
1437 no_sanitize_address = 100,
1438 no_sanitize_hwaddress = 101,
1439 //sanitize_memtag,
1440 sanitize_address_dyninit = 102,
1874 //alignstack = @intFromEnum(ATTR_KIND.STACK_ALIGNMENT),
1875 allockind = @backingInt(ATTR_KIND.ALLOC_KIND),
1876 allocsize = @backingInt(ATTR_KIND.ALLOC_SIZE),
1877 alwaysinline = @backingInt(ATTR_KIND.ALWAYS_INLINE),
1878 builtin = @backingInt(ATTR_KIND.BUILTIN),
1879 cold = @backingInt(ATTR_KIND.COLD),
1880 convergent = @backingInt(ATTR_KIND.CONVERGENT),
1881 disable_sanitizer_instrumentation = @backingInt(ATTR_KIND.DISABLE_SANITIZER_INSTRUMENTATION),
1882 fn_ret_thunk_extern = @backingInt(ATTR_KIND.FNRETTHUNK_EXTERN),
1883 hot = @backingInt(ATTR_KIND.HOT),
1884 inlinehint = @backingInt(ATTR_KIND.INLINE_HINT),
1885 jumptable = @backingInt(ATTR_KIND.JUMP_TABLE),
1886 memory = @backingInt(ATTR_KIND.MEMORY),
1887 minsize = @backingInt(ATTR_KIND.MIN_SIZE),
1888 naked = @backingInt(ATTR_KIND.NAKED),
1889 nobuiltin = @backingInt(ATTR_KIND.NO_BUILTIN),
1890 nocallback = @backingInt(ATTR_KIND.NO_CALLBACK),
1891 nodivergencesource = @backingInt(ATTR_KIND.NO_DIVERGENCE_SOURCE),
1892 noduplicate = @backingInt(ATTR_KIND.NO_DUPLICATE),
1893 //nofree = @intFromEnum(ATTR_KIND.NOFREE),
1894 noimplicitfloat = @backingInt(ATTR_KIND.NO_IMPLICIT_FLOAT),
1895 @"noinline" = @backingInt(ATTR_KIND.NO_INLINE),
1896 nomerge = @backingInt(ATTR_KIND.NO_MERGE),
1897 nonlazybind = @backingInt(ATTR_KIND.NON_LAZY_BIND),
1898 noprofile = @backingInt(ATTR_KIND.NO_PROFILE),
1899 skipprofile = @backingInt(ATTR_KIND.SKIP_PROFILE),
1900 noredzone = @backingInt(ATTR_KIND.NO_RED_ZONE),
1901 noreturn = @backingInt(ATTR_KIND.NO_RETURN),
1902 norecurse = @backingInt(ATTR_KIND.NO_RECURSE),
1903 willreturn = @backingInt(ATTR_KIND.WILLRETURN),
1904 nosync = @backingInt(ATTR_KIND.NOSYNC),
1905 nounwind = @backingInt(ATTR_KIND.NO_UNWIND),
1906 nosanitize_bounds = @backingInt(ATTR_KIND.NO_SANITIZE_BOUNDS),
1907 nosanitize_coverage = @backingInt(ATTR_KIND.NO_SANITIZE_COVERAGE),
1908 null_pointer_is_valid = @backingInt(ATTR_KIND.NULL_POINTER_IS_VALID),
1909 optdebug = @backingInt(ATTR_KIND.OPTIMIZE_FOR_DEBUGGING),
1910 optforfuzzing = @backingInt(ATTR_KIND.OPT_FOR_FUZZING),
1911 optnone = @backingInt(ATTR_KIND.OPTIMIZE_NONE),
1912 optsize = @backingInt(ATTR_KIND.OPTIMIZE_FOR_SIZE),
1913 //preallocated = @intFromEnum(ATTR_KIND.PREALLOCATED),
1914 returns_twice = @backingInt(ATTR_KIND.RETURNS_TWICE),
1915 safestack = @backingInt(ATTR_KIND.SAFESTACK),
1916 sanitize_address = @backingInt(ATTR_KIND.SANITIZE_ADDRESS),
1917 sanitize_memory = @backingInt(ATTR_KIND.SANITIZE_MEMORY),
1918 sanitize_thread = @backingInt(ATTR_KIND.SANITIZE_THREAD),
1919 sanitize_hwaddress = @backingInt(ATTR_KIND.SANITIZE_HWADDRESS),
1920 sanitize_memtag = @backingInt(ATTR_KIND.SANITIZE_MEMTAG),
1921 sanitize_realtime = @backingInt(ATTR_KIND.SANITIZE_REALTIME),
1922 sanitize_realtime_blocking = @backingInt(ATTR_KIND.SANITIZE_REALTIME_BLOCKING),
1923 sanitize_alloc_token = @backingInt(ATTR_KIND.SANITIZE_ALLOC_TOKEN),
1924 speculative_load_hardening = @backingInt(ATTR_KIND.SPECULATIVE_LOAD_HARDENING),
1925 speculatable = @backingInt(ATTR_KIND.SPECULATABLE),
1926 ssp = @backingInt(ATTR_KIND.STACK_PROTECT),
1927 sspstrong = @backingInt(ATTR_KIND.STACK_PROTECT_STRONG),
1928 sspreq = @backingInt(ATTR_KIND.STACK_PROTECT_REQ),
1929 strictfp = @backingInt(ATTR_KIND.STRICT_FP),
1930 denormal_fpenv = @backingInt(ATTR_KIND.DENORMAL_FPENV),
1931 uwtable = @backingInt(ATTR_KIND.UW_TABLE),
1932 nocf_check = @backingInt(ATTR_KIND.NOCF_CHECK),
1933 shadowcallstack = @backingInt(ATTR_KIND.SHADOWCALLSTACK),
1934 mustprogress = @backingInt(ATTR_KIND.MUSTPROGRESS),
1935 vscale_range = @backingInt(ATTR_KIND.VSCALE_RANGE),
1936 nooutline = @backingInt(ATTR_KIND.NOOUTLINE),
1937 nocreateundeforpoison = @backingInt(ATTR_KIND.NO_CREATE_UNDEF_OR_POISON),
14411938
14421939 string = maxInt(u31),
14431940 none = maxInt(u32),
......@@ -1447,16 +1944,128 @@ pub const Attribute = union(Kind) {
14471944
14481945 pub fn fromString(str: String) Kind {
14491946 assert(!str.isAnon());
1450 const kind: Kind = @fromBackingInt(@intCast(@backingInt(str)));
1947 const kind: Kind = @fromBackingInt(@backingInt(str));
14511948 assert(kind != .none);
14521949 return kind;
14531950 }
14541951
14551952 fn toString(self: Kind) ?String {
14561953 assert(self != .none);
1457 const str: String = @fromBackingInt(@intCast(@backingInt(self)));
1954 const str: String = @fromBackingInt(@backingInt(self));
14581955 return if (str.isAnon()) null else str;
14591956 }
1957
1958 /// enum AttributeKindCodes
1959 const ATTR_KIND = enum(u32) {
1960 ALIGNMENT = 1,
1961 ALWAYS_INLINE = 2,
1962 BY_VAL = 3,
1963 INLINE_HINT = 4,
1964 IN_REG = 5,
1965 MIN_SIZE = 6,
1966 NAKED = 7,
1967 NEST = 8,
1968 NO_ALIAS = 9,
1969 NO_BUILTIN = 10,
1970 NO_CAPTURE = 11,
1971 NO_DUPLICATE = 12,
1972 NO_IMPLICIT_FLOAT = 13,
1973 NO_INLINE = 14,
1974 NON_LAZY_BIND = 15,
1975 NO_RED_ZONE = 16,
1976 NO_RETURN = 17,
1977 NO_UNWIND = 18,
1978 OPTIMIZE_FOR_SIZE = 19,
1979 READ_NONE = 20,
1980 READ_ONLY = 21,
1981 RETURNED = 22,
1982 RETURNS_TWICE = 23,
1983 S_EXT = 24,
1984 STACK_ALIGNMENT = 25,
1985 STACK_PROTECT = 26,
1986 STACK_PROTECT_REQ = 27,
1987 STACK_PROTECT_STRONG = 28,
1988 STRUCT_RET = 29,
1989 SANITIZE_ADDRESS = 30,
1990 SANITIZE_THREAD = 31,
1991 SANITIZE_MEMORY = 32,
1992 UW_TABLE = 33,
1993 Z_EXT = 34,
1994 BUILTIN = 35,
1995 COLD = 36,
1996 OPTIMIZE_NONE = 37,
1997 IN_ALLOCA = 38,
1998 NON_NULL = 39,
1999 JUMP_TABLE = 40,
2000 DEREFERENCEABLE = 41,
2001 DEREFERENCEABLE_OR_NULL = 42,
2002 CONVERGENT = 43,
2003 SAFESTACK = 44,
2004 ARGMEMONLY = 45,
2005 SWIFT_SELF = 46,
2006 SWIFT_ERROR = 47,
2007 NO_RECURSE = 48,
2008 INACCESSIBLEMEM_ONLY = 49,
2009 INACCESSIBLEMEM_OR_ARGMEMONLY = 50,
2010 ALLOC_SIZE = 51,
2011 WRITEONLY = 52,
2012 SPECULATABLE = 53,
2013 STRICT_FP = 54,
2014 SANITIZE_HWADDRESS = 55,
2015 NOCF_CHECK = 56,
2016 OPT_FOR_FUZZING = 57,
2017 SHADOWCALLSTACK = 58,
2018 SPECULATIVE_LOAD_HARDENING = 59,
2019 IMMARG = 60,
2020 WILLRETURN = 61,
2021 NOFREE = 62,
2022 NOSYNC = 63,
2023 SANITIZE_MEMTAG = 64,
2024 PREALLOCATED = 65,
2025 NO_MERGE = 66,
2026 NULL_POINTER_IS_VALID = 67,
2027 NOUNDEF = 68,
2028 BYREF = 69,
2029 MUSTPROGRESS = 70,
2030 NO_CALLBACK = 71,
2031 HOT = 72,
2032 NO_PROFILE = 73,
2033 VSCALE_RANGE = 74,
2034 SWIFT_ASYNC = 75,
2035 NO_SANITIZE_COVERAGE = 76,
2036 ELEMENTTYPE = 77,
2037 DISABLE_SANITIZER_INSTRUMENTATION = 78,
2038 NO_SANITIZE_BOUNDS = 79,
2039 ALLOC_ALIGN = 80,
2040 ALLOCATED_POINTER = 81,
2041 ALLOC_KIND = 82,
2042 PRESPLIT_COROUTINE = 83,
2043 FNRETTHUNK_EXTERN = 84,
2044 SKIP_PROFILE = 85,
2045 MEMORY = 86,
2046 NOFPCLASS = 87,
2047 OPTIMIZE_FOR_DEBUGGING = 88,
2048 WRITABLE = 89,
2049 CORO_ONLY_DESTROY_WHEN_COMPLETE = 90,
2050 DEAD_ON_UNWIND = 91,
2051 RANGE = 92,
2052 SANITIZE_NUMERICAL_STABILITY = 93,
2053 INITIALIZES = 94,
2054 HYBRID_PATCHABLE = 95,
2055 SANITIZE_REALTIME = 96,
2056 SANITIZE_REALTIME_BLOCKING = 97,
2057 CORO_ELIDE_SAFE = 98,
2058 NO_EXT = 99,
2059 NO_DIVERGENCE_SOURCE = 100,
2060 SANITIZE_TYPE = 101,
2061 CAPTURES = 102,
2062 DEAD_ON_RETURN = 103,
2063 SANITIZE_ALLOC_TOKEN = 104,
2064 NO_CREATE_UNDEF_OR_POISON = 105,
2065 DENORMAL_FPENV = 106,
2066 NOOUTLINE = 107,
2067 FLATTEN = 108,
2068 };
14602069 };
14612070
14622071 pub const FpClass = packed struct(u32) {
......@@ -1506,6 +2115,29 @@ pub const Attribute = union(Kind) {
15062115 pub const pnorm = FpClass{ .positive_normal = true };
15072116 };
15082117
2118 pub const Captures = packed struct(u32) {
2119 other: Components = .none,
2120 ret: Components = .none,
2121 _: u24 = 0,
2122
2123 pub const none: Captures = .{};
2124
2125 pub const Components = packed struct(u4) {
2126 address_is_null: bool = false,
2127 address: bool = false,
2128 read_provenance: bool = false,
2129 provenance: bool = false,
2130
2131 pub const none: Components = .{};
2132 pub const all: Components = .{
2133 .address_is_null = true,
2134 .address = true,
2135 .read_provenance = true,
2136 .provenance = true,
2137 };
2138 };
2139 };
2140
15092141 pub const AllocKind = packed struct(u32) {
15102142 alloc: bool,
15112143 realloc: bool,
......@@ -1582,9 +2214,13 @@ pub const Attribute = union(Kind) {
15822214 void => 0,
15832215 u32 => value,
15842216 Alignment.Lazy, String, Type, UwTable => @backingInt(value),
1585 AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value),
1586 else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))),
2217 AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(value),
2218 else => @compileError("bad payload type: " ++ @tagName(tag) ++ ": " ++ @typeName(@TypeOf(value))),
15872219 } },
2220 .initializes,
2221 .dead_on_return,
2222 .range,
2223 => @panic("TODO"),
15882224 .string => |string_attr| .{
15892225 .kind = Kind.fromString(string_attr.kind),
15902226 .value = @backingInt(string_attr.value),
......@@ -1907,87 +2543,87 @@ pub const AddrSpace = enum(u24) {
19072543
19082544 // See llvm/lib/Target/X86/X86.h
19092545 pub const x86 = struct {
1910 pub const gs: AddrSpace = @fromBackingInt(@intCast(256));
1911 pub const fs: AddrSpace = @fromBackingInt(@intCast(257));
1912 pub const ss: AddrSpace = @fromBackingInt(@intCast(258));
2546 pub const gs: AddrSpace = @fromBackingInt(256);
2547 pub const fs: AddrSpace = @fromBackingInt(257);
2548 pub const ss: AddrSpace = @fromBackingInt(258);
19132549
1914 pub const ptr32_sptr: AddrSpace = @fromBackingInt(@intCast(270));
1915 pub const ptr32_uptr: AddrSpace = @fromBackingInt(@intCast(271));
1916 pub const ptr64: AddrSpace = @fromBackingInt(@intCast(272));
2550 pub const ptr32_sptr: AddrSpace = @fromBackingInt(270);
2551 pub const ptr32_uptr: AddrSpace = @fromBackingInt(271);
2552 pub const ptr64: AddrSpace = @fromBackingInt(272);
19172553 };
19182554 pub const x86_64 = x86;
19192555
19202556 // See llvm/lib/Target/AVR/AVR.h
19212557 pub const avr = struct {
1922 pub const data: AddrSpace = @fromBackingInt(@intCast(0));
1923 pub const program: AddrSpace = @fromBackingInt(@intCast(1));
1924 pub const program1: AddrSpace = @fromBackingInt(@intCast(2));
1925 pub const program2: AddrSpace = @fromBackingInt(@intCast(3));
1926 pub const program3: AddrSpace = @fromBackingInt(@intCast(4));
1927 pub const program4: AddrSpace = @fromBackingInt(@intCast(5));
1928 pub const program5: AddrSpace = @fromBackingInt(@intCast(6));
2558 pub const data: AddrSpace = @fromBackingInt(0);
2559 pub const program: AddrSpace = @fromBackingInt(1);
2560 pub const program1: AddrSpace = @fromBackingInt(2);
2561 pub const program2: AddrSpace = @fromBackingInt(3);
2562 pub const program3: AddrSpace = @fromBackingInt(4);
2563 pub const program4: AddrSpace = @fromBackingInt(5);
2564 pub const program5: AddrSpace = @fromBackingInt(6);
19292565 };
19302566
19312567 // See llvm/lib/Target/NVPTX/NVPTX.h
19322568 pub const nvptx = struct {
1933 pub const generic: AddrSpace = @fromBackingInt(@intCast(0));
1934 pub const global: AddrSpace = @fromBackingInt(@intCast(1));
1935 pub const constant: AddrSpace = @fromBackingInt(@intCast(2));
1936 pub const shared: AddrSpace = @fromBackingInt(@intCast(3));
1937 pub const param: AddrSpace = @fromBackingInt(@intCast(4));
1938 pub const local: AddrSpace = @fromBackingInt(@intCast(5));
2569 pub const generic: AddrSpace = @fromBackingInt(0);
2570 pub const global: AddrSpace = @fromBackingInt(1);
2571 pub const constant: AddrSpace = @fromBackingInt(2);
2572 pub const shared: AddrSpace = @fromBackingInt(3);
2573 pub const param: AddrSpace = @fromBackingInt(4);
2574 pub const local: AddrSpace = @fromBackingInt(5);
19392575 };
19402576
19412577 // See llvm/lib/Target/AMDGPU/AMDGPU.h
19422578 pub const amdgpu = struct {
1943 pub const flat: AddrSpace = @fromBackingInt(@intCast(0));
1944 pub const global: AddrSpace = @fromBackingInt(@intCast(1));
1945 pub const region: AddrSpace = @fromBackingInt(@intCast(2));
1946 pub const local: AddrSpace = @fromBackingInt(@intCast(3));
1947 pub const constant: AddrSpace = @fromBackingInt(@intCast(4));
1948 pub const private: AddrSpace = @fromBackingInt(@intCast(5));
1949 pub const constant_32bit: AddrSpace = @fromBackingInt(@intCast(6));
1950 pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(@intCast(7));
1951 pub const buffer_resource: AddrSpace = @fromBackingInt(@intCast(8));
1952 pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(@intCast(9));
1953 pub const param_d: AddrSpace = @fromBackingInt(@intCast(6));
1954 pub const param_i: AddrSpace = @fromBackingInt(@intCast(7));
1955 pub const constant_buffer_0: AddrSpace = @fromBackingInt(@intCast(8));
1956 pub const constant_buffer_1: AddrSpace = @fromBackingInt(@intCast(9));
1957 pub const constant_buffer_2: AddrSpace = @fromBackingInt(@intCast(10));
1958 pub const constant_buffer_3: AddrSpace = @fromBackingInt(@intCast(11));
1959 pub const constant_buffer_4: AddrSpace = @fromBackingInt(@intCast(12));
1960 pub const constant_buffer_5: AddrSpace = @fromBackingInt(@intCast(13));
1961 pub const constant_buffer_6: AddrSpace = @fromBackingInt(@intCast(14));
1962 pub const constant_buffer_7: AddrSpace = @fromBackingInt(@intCast(15));
1963 pub const constant_buffer_8: AddrSpace = @fromBackingInt(@intCast(16));
1964 pub const constant_buffer_9: AddrSpace = @fromBackingInt(@intCast(17));
1965 pub const constant_buffer_10: AddrSpace = @fromBackingInt(@intCast(18));
1966 pub const constant_buffer_11: AddrSpace = @fromBackingInt(@intCast(19));
1967 pub const constant_buffer_12: AddrSpace = @fromBackingInt(@intCast(20));
1968 pub const constant_buffer_13: AddrSpace = @fromBackingInt(@intCast(21));
1969 pub const constant_buffer_14: AddrSpace = @fromBackingInt(@intCast(22));
1970 pub const constant_buffer_15: AddrSpace = @fromBackingInt(@intCast(23));
1971 pub const streamout_register: AddrSpace = @fromBackingInt(@intCast(128));
2579 pub const flat: AddrSpace = @fromBackingInt(0);
2580 pub const global: AddrSpace = @fromBackingInt(1);
2581 pub const region: AddrSpace = @fromBackingInt(2);
2582 pub const local: AddrSpace = @fromBackingInt(3);
2583 pub const constant: AddrSpace = @fromBackingInt(4);
2584 pub const private: AddrSpace = @fromBackingInt(5);
2585 pub const constant_32bit: AddrSpace = @fromBackingInt(6);
2586 pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(7);
2587 pub const buffer_resource: AddrSpace = @fromBackingInt(8);
2588 pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(9);
2589 pub const param_d: AddrSpace = @fromBackingInt(6);
2590 pub const param_i: AddrSpace = @fromBackingInt(7);
2591 pub const constant_buffer_0: AddrSpace = @fromBackingInt(8);
2592 pub const constant_buffer_1: AddrSpace = @fromBackingInt(9);
2593 pub const constant_buffer_2: AddrSpace = @fromBackingInt(10);
2594 pub const constant_buffer_3: AddrSpace = @fromBackingInt(11);
2595 pub const constant_buffer_4: AddrSpace = @fromBackingInt(12);
2596 pub const constant_buffer_5: AddrSpace = @fromBackingInt(13);
2597 pub const constant_buffer_6: AddrSpace = @fromBackingInt(14);
2598 pub const constant_buffer_7: AddrSpace = @fromBackingInt(15);
2599 pub const constant_buffer_8: AddrSpace = @fromBackingInt(16);
2600 pub const constant_buffer_9: AddrSpace = @fromBackingInt(17);
2601 pub const constant_buffer_10: AddrSpace = @fromBackingInt(18);
2602 pub const constant_buffer_11: AddrSpace = @fromBackingInt(19);
2603 pub const constant_buffer_12: AddrSpace = @fromBackingInt(20);
2604 pub const constant_buffer_13: AddrSpace = @fromBackingInt(21);
2605 pub const constant_buffer_14: AddrSpace = @fromBackingInt(22);
2606 pub const constant_buffer_15: AddrSpace = @fromBackingInt(23);
2607 pub const streamout_register: AddrSpace = @fromBackingInt(128);
19722608 };
19732609
19742610 pub const spirv = struct {
1975 pub const function: AddrSpace = @fromBackingInt(@intCast(0));
1976 pub const cross_workgroup: AddrSpace = @fromBackingInt(@intCast(1));
1977 pub const uniform_constant: AddrSpace = @fromBackingInt(@intCast(2));
1978 pub const workgroup: AddrSpace = @fromBackingInt(@intCast(3));
1979 pub const generic: AddrSpace = @fromBackingInt(@intCast(4));
1980 pub const device_only_intel: AddrSpace = @fromBackingInt(@intCast(5));
1981 pub const host_only_intel: AddrSpace = @fromBackingInt(@intCast(6));
1982 pub const input: AddrSpace = @fromBackingInt(@intCast(7));
2611 pub const function: AddrSpace = @fromBackingInt(0);
2612 pub const cross_workgroup: AddrSpace = @fromBackingInt(1);
2613 pub const uniform_constant: AddrSpace = @fromBackingInt(2);
2614 pub const workgroup: AddrSpace = @fromBackingInt(3);
2615 pub const generic: AddrSpace = @fromBackingInt(4);
2616 pub const device_only_intel: AddrSpace = @fromBackingInt(5);
2617 pub const host_only_intel: AddrSpace = @fromBackingInt(6);
2618 pub const input: AddrSpace = @fromBackingInt(7);
19832619 };
19842620
19852621 // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h
19862622 pub const wasm = struct {
1987 pub const default: AddrSpace = @fromBackingInt(@intCast(0));
1988 pub const variable: AddrSpace = @fromBackingInt(@intCast(1));
1989 pub const externref: AddrSpace = @fromBackingInt(@intCast(10));
1990 pub const funcref: AddrSpace = @fromBackingInt(@intCast(20));
2623 pub const default: AddrSpace = @fromBackingInt(0);
2624 pub const variable: AddrSpace = @fromBackingInt(1);
2625 pub const externref: AddrSpace = @fromBackingInt(10);
2626 pub const funcref: AddrSpace = @fromBackingInt(20);
19912627 };
19922628
19932629 pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void {
......@@ -2030,7 +2666,7 @@ pub const Alignment = enum(u6) {
20302666 _,
20312667
20322668 pub fn wrap(a: Alignment) Lazy {
2033 return @fromBackingInt(@intCast(@backingInt(a)));
2669 return @fromBackingInt(@backingInt(a));
20342670 }
20352671 pub fn resolve(l: Lazy, b: *const Builder) Alignment {
20362672 return switch (@backingInt(l)) {
......@@ -2061,11 +2697,18 @@ pub const Alignment = enum(u6) {
20612697 };
20622698 }
20632699
2064 /// Asserts that neither `a` nor `b` is `.default`.
2065 pub fn max(a: Alignment, b: Alignment) Alignment {
2066 assert(a != .default);
2067 assert(b != .default);
2068 return @fromBackingInt(@intCast(@max(@backingInt(a), @backingInt(b))));
2700 /// Asserts that neither `lhs` nor `rhs` is `.default`.
2701 pub fn max(lhs: Alignment, rhs: Alignment) Alignment {
2702 assert(lhs != .default);
2703 assert(rhs != .default);
2704 return @fromBackingInt(@max(@backingInt(lhs), @backingInt(rhs)));
2705 }
2706
2707 /// Asserts that neither `lhs` nor `rhs` is `.default`.
2708 pub fn order(lhs: Alignment, rhs: Alignment) std.math.Order {
2709 assert(lhs != .default);
2710 assert(rhs != .default);
2711 return std.math.order(@backingInt(lhs), @backingInt(rhs));
20692712 }
20702713
20712714 pub fn toLlvm(self: Alignment) u6 {
......@@ -2261,8 +2904,7 @@ pub const StrtabString = enum(u32) {
22612904 }
22622905
22632906 fn fromIndex(index: ?usize) StrtabString {
2264 return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) +
2265 @backingInt(StrtabString.empty)))));
2907 return @fromBackingInt(@intCast((index orelse return .none) + @backingInt(StrtabString.empty)));
22662908 }
22672909
22682910 fn toIndex(self: StrtabString) ?usize {
......@@ -2398,7 +3040,7 @@ pub const Global = struct {
23983040 }
23993041
24003042 pub fn toConst(global: Index) Constant {
2401 return @fromBackingInt(@intCast(@backingInt(Constant.first_global) + @backingInt(global)));
3043 return @fromBackingInt(@backingInt(Constant.first_global) + @backingInt(global));
24023044 }
24033045
24043046 pub fn toValue(global: Index) Value {
......@@ -2526,7 +3168,7 @@ pub const Global = struct {
25263168 _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
25273169 builder.globals.swapRemoveAt(index);
25283170 if (!old_name.isAnon()) return;
2529 builder.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(builder.next_unnamed_global) - 1));
3171 builder.next_unnamed_global = @fromBackingInt(@backingInt(builder.next_unnamed_global) - 1);
25303172 if (builder.next_unnamed_global == old_name) return;
25313173 builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder);
25323174 }
......@@ -2539,7 +3181,7 @@ pub const Global = struct {
25393181
25403182 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
25413183 if (self.eql(other, builder)) return;
2542 builder.next_replaced_global = @fromBackingInt(@intCast(@backingInt(builder.next_replaced_global) - 1));
3184 builder.next_replaced_global = @fromBackingInt(@backingInt(builder.next_replaced_global) - 1);
25433185 self.renameAssumeCapacity(builder.next_replaced_global, builder);
25443186 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
25453187 }
......@@ -2699,6 +3341,8 @@ pub const Intrinsic = enum {
26993341 smin,
27003342 umax,
27013343 umin,
3344 scmp,
3345 ucmp,
27023346 memcpy,
27033347 @"memcpy.inline",
27043348 memmove,
......@@ -2708,10 +3352,21 @@ pub const Intrinsic = enum {
27083352 powi,
27093353 sin,
27103354 cos,
3355 tan,
3356 asin,
3357 acos,
3358 atan,
3359 atan2,
3360 sinh,
3361 cosh,
3362 tanh,
3363 sincos,
3364 sincospi,
3365 modf,
27113366 pow,
27123367 exp,
2713 exp10,
27143368 exp2,
3369 exp10,
27153370 ldexp,
27163371 frexp,
27173372 log,
......@@ -2723,6 +3378,8 @@ pub const Intrinsic = enum {
27233378 maxnum,
27243379 minimum,
27253380 maximum,
3381 minimumnum,
3382 maximumnum,
27263383 copysign,
27273384 floor,
27283385 ceil,
......@@ -2744,6 +3401,7 @@ pub const Intrinsic = enum {
27443401 cttz,
27453402 fshl,
27463403 fshr,
3404 clmul,
27473405
27483406 // Arithmetic with Overflow
27493407 @"sadd.with.overflow",
......@@ -2904,21 +3562,21 @@ pub const Intrinsic = enum {
29043562 .{ .kind = .{ .type = .ptr } },
29053563 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29063564 },
2907 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3565 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29083566 },
29093567 .addressofreturnaddress = .{
29103568 .ret_len = 1,
29113569 .params = &.{
29123570 .{ .kind = .overloaded },
29133571 },
2914 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3572 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29153573 },
29163574 .sponentry = .{
29173575 .ret_len = 1,
29183576 .params = &.{
29193577 .{ .kind = .overloaded },
29203578 },
2921 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3579 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29223580 },
29233581 .frameaddress = .{
29243582 .ret_len = 1,
......@@ -2926,7 +3584,7 @@ pub const Intrinsic = enum {
29263584 .{ .kind = .overloaded },
29273585 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29283586 },
2929 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3587 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29303588 },
29313589 .prefetch = .{
29323590 .ret_len = 0,
......@@ -2936,14 +3594,14 @@ pub const Intrinsic = enum {
29363594 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29373595 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
29383596 },
2939 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } },
3597 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.readwrite) } },
29403598 },
29413599 .@"thread.pointer" = .{
29423600 .ret_len = 1,
29433601 .params = &.{
29443602 .{ .kind = .{ .type = .ptr } },
29453603 },
2946 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3604 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
29473605 },
29483606
29493607 .abs = .{
......@@ -2953,7 +3611,7 @@ pub const Intrinsic = enum {
29533611 .{ .kind = .{ .matches = 0 } },
29543612 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
29553613 },
2956 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3614 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29573615 },
29583616 .smax = .{
29593617 .ret_len = 1,
......@@ -2962,7 +3620,7 @@ pub const Intrinsic = enum {
29623620 .{ .kind = .{ .matches = 0 } },
29633621 .{ .kind = .{ .matches = 0 } },
29643622 },
2965 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3623 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29663624 },
29673625 .smin = .{
29683626 .ret_len = 1,
......@@ -2971,7 +3629,7 @@ pub const Intrinsic = enum {
29713629 .{ .kind = .{ .matches = 0 } },
29723630 .{ .kind = .{ .matches = 0 } },
29733631 },
2974 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3632 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29753633 },
29763634 .umax = .{
29773635 .ret_len = 1,
......@@ -2980,7 +3638,7 @@ pub const Intrinsic = enum {
29803638 .{ .kind = .{ .matches = 0 } },
29813639 .{ .kind = .{ .matches = 0 } },
29823640 },
2983 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3641 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29843642 },
29853643 .umin = .{
29863644 .ret_len = 1,
......@@ -2989,7 +3647,25 @@ pub const Intrinsic = enum {
29893647 .{ .kind = .{ .matches = 0 } },
29903648 .{ .kind = .{ .matches = 0 } },
29913649 },
2992 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3650 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3651 },
3652 .scmp = .{
3653 .ret_len = 1,
3654 .params = &.{
3655 .{ .kind = .overloaded },
3656 .{ .kind = .overloaded },
3657 .{ .kind = .{ .matches = 1 } },
3658 },
3659 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3660 },
3661 .ucmp = .{
3662 .ret_len = 1,
3663 .params = &.{
3664 .{ .kind = .overloaded },
3665 .{ .kind = .overloaded },
3666 .{ .kind = .{ .matches = 1 } },
3667 },
3668 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
29933669 },
29943670 .memcpy = .{
29953671 .ret_len = 0,
......@@ -3047,7 +3723,7 @@ pub const Intrinsic = enum {
30473723 .{ .kind = .overloaded },
30483724 .{ .kind = .{ .matches = 0 } },
30493725 },
3050 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3726 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30513727 },
30523728 .powi = .{
30533729 .ret_len = 1,
......@@ -3056,7 +3732,7 @@ pub const Intrinsic = enum {
30563732 .{ .kind = .{ .matches = 0 } },
30573733 .{ .kind = .overloaded },
30583734 },
3059 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3735 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30603736 },
30613737 .sin = .{
30623738 .ret_len = 1,
......@@ -3064,7 +3740,7 @@ pub const Intrinsic = enum {
30643740 .{ .kind = .overloaded },
30653741 .{ .kind = .{ .matches = 0 } },
30663742 },
3067 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3743 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30683744 },
30693745 .cos = .{
30703746 .ret_len = 1,
......@@ -3072,7 +3748,99 @@ pub const Intrinsic = enum {
30723748 .{ .kind = .overloaded },
30733749 .{ .kind = .{ .matches = 0 } },
30743750 },
3075 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3751 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3752 },
3753 .tan = .{
3754 .ret_len = 1,
3755 .params = &.{
3756 .{ .kind = .overloaded },
3757 .{ .kind = .{ .matches = 0 } },
3758 },
3759 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3760 },
3761 .asin = .{
3762 .ret_len = 1,
3763 .params = &.{
3764 .{ .kind = .overloaded },
3765 .{ .kind = .{ .matches = 0 } },
3766 },
3767 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3768 },
3769 .acos = .{
3770 .ret_len = 1,
3771 .params = &.{
3772 .{ .kind = .overloaded },
3773 .{ .kind = .{ .matches = 0 } },
3774 },
3775 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3776 },
3777 .atan = .{
3778 .ret_len = 1,
3779 .params = &.{
3780 .{ .kind = .overloaded },
3781 .{ .kind = .{ .matches = 0 } },
3782 },
3783 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3784 },
3785 .atan2 = .{
3786 .ret_len = 1,
3787 .params = &.{
3788 .{ .kind = .overloaded },
3789 .{ .kind = .{ .matches = 0 } },
3790 .{ .kind = .{ .matches = 0 } },
3791 },
3792 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3793 },
3794 .sinh = .{
3795 .ret_len = 1,
3796 .params = &.{
3797 .{ .kind = .overloaded },
3798 .{ .kind = .{ .matches = 0 } },
3799 },
3800 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3801 },
3802 .cosh = .{
3803 .ret_len = 1,
3804 .params = &.{
3805 .{ .kind = .overloaded },
3806 .{ .kind = .{ .matches = 0 } },
3807 },
3808 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3809 },
3810 .tanh = .{
3811 .ret_len = 1,
3812 .params = &.{
3813 .{ .kind = .overloaded },
3814 .{ .kind = .{ .matches = 0 } },
3815 },
3816 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3817 },
3818 .sincos = .{
3819 .ret_len = 2,
3820 .params = &.{
3821 .{ .kind = .overloaded },
3822 .{ .kind = .{ .matches = 0 } },
3823 .{ .kind = .{ .matches = 0 } },
3824 },
3825 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3826 },
3827 .sincospi = .{
3828 .ret_len = 2,
3829 .params = &.{
3830 .{ .kind = .overloaded },
3831 .{ .kind = .{ .matches = 0 } },
3832 .{ .kind = .{ .matches = 0 } },
3833 },
3834 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3835 },
3836 .modf = .{
3837 .ret_len = 2,
3838 .params = &.{
3839 .{ .kind = .overloaded },
3840 .{ .kind = .{ .matches = 0 } },
3841 .{ .kind = .{ .matches = 0 } },
3842 },
3843 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30763844 },
30773845 .pow = .{
30783846 .ret_len = 1,
......@@ -3081,7 +3849,7 @@ pub const Intrinsic = enum {
30813849 .{ .kind = .{ .matches = 0 } },
30823850 .{ .kind = .{ .matches = 0 } },
30833851 },
3084 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3852 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30853853 },
30863854 .exp = .{
30873855 .ret_len = 1,
......@@ -3089,7 +3857,7 @@ pub const Intrinsic = enum {
30893857 .{ .kind = .overloaded },
30903858 .{ .kind = .{ .matches = 0 } },
30913859 },
3092 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3860 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
30933861 },
30943862 .exp2 = .{
30953863 .ret_len = 1,
......@@ -3097,7 +3865,7 @@ pub const Intrinsic = enum {
30973865 .{ .kind = .overloaded },
30983866 .{ .kind = .{ .matches = 0 } },
30993867 },
3100 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3868 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31013869 },
31023870 .exp10 = .{
31033871 .ret_len = 1,
......@@ -3105,7 +3873,7 @@ pub const Intrinsic = enum {
31053873 .{ .kind = .overloaded },
31063874 .{ .kind = .{ .matches = 0 } },
31073875 },
3108 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3876 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31093877 },
31103878 .ldexp = .{
31113879 .ret_len = 1,
......@@ -3114,7 +3882,7 @@ pub const Intrinsic = enum {
31143882 .{ .kind = .{ .matches = 0 } },
31153883 .{ .kind = .overloaded },
31163884 },
3117 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3885 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31183886 },
31193887 .frexp = .{
31203888 .ret_len = 2,
......@@ -3123,7 +3891,7 @@ pub const Intrinsic = enum {
31233891 .{ .kind = .overloaded },
31243892 .{ .kind = .{ .matches = 0 } },
31253893 },
3126 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3894 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31273895 },
31283896 .log = .{
31293897 .ret_len = 1,
......@@ -3131,7 +3899,7 @@ pub const Intrinsic = enum {
31313899 .{ .kind = .overloaded },
31323900 .{ .kind = .{ .matches = 0 } },
31333901 },
3134 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3902 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31353903 },
31363904 .log10 = .{
31373905 .ret_len = 1,
......@@ -3139,7 +3907,7 @@ pub const Intrinsic = enum {
31393907 .{ .kind = .overloaded },
31403908 .{ .kind = .{ .matches = 0 } },
31413909 },
3142 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3910 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31433911 },
31443912 .log2 = .{
31453913 .ret_len = 1,
......@@ -3147,7 +3915,7 @@ pub const Intrinsic = enum {
31473915 .{ .kind = .overloaded },
31483916 .{ .kind = .{ .matches = 0 } },
31493917 },
3150 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3918 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31513919 },
31523920 .fma = .{
31533921 .ret_len = 1,
......@@ -3157,7 +3925,7 @@ pub const Intrinsic = enum {
31573925 .{ .kind = .{ .matches = 0 } },
31583926 .{ .kind = .{ .matches = 0 } },
31593927 },
3160 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3928 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31613929 },
31623930 .fabs = .{
31633931 .ret_len = 1,
......@@ -3165,7 +3933,7 @@ pub const Intrinsic = enum {
31653933 .{ .kind = .overloaded },
31663934 .{ .kind = .{ .matches = 0 } },
31673935 },
3168 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3936 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31693937 },
31703938 .minnum = .{
31713939 .ret_len = 1,
......@@ -3174,7 +3942,7 @@ pub const Intrinsic = enum {
31743942 .{ .kind = .{ .matches = 0 } },
31753943 .{ .kind = .{ .matches = 0 } },
31763944 },
3177 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3945 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31783946 },
31793947 .maxnum = .{
31803948 .ret_len = 1,
......@@ -3183,7 +3951,7 @@ pub const Intrinsic = enum {
31833951 .{ .kind = .{ .matches = 0 } },
31843952 .{ .kind = .{ .matches = 0 } },
31853953 },
3186 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3954 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31873955 },
31883956 .minimum = .{
31893957 .ret_len = 1,
......@@ -3192,7 +3960,7 @@ pub const Intrinsic = enum {
31923960 .{ .kind = .{ .matches = 0 } },
31933961 .{ .kind = .{ .matches = 0 } },
31943962 },
3195 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3963 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
31963964 },
31973965 .maximum = .{
31983966 .ret_len = 1,
......@@ -3201,7 +3969,25 @@ pub const Intrinsic = enum {
32013969 .{ .kind = .{ .matches = 0 } },
32023970 .{ .kind = .{ .matches = 0 } },
32033971 },
3204 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3972 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3973 },
3974 .minimumnum = .{
3975 .ret_len = 1,
3976 .params = &.{
3977 .{ .kind = .overloaded },
3978 .{ .kind = .{ .matches = 0 } },
3979 .{ .kind = .{ .matches = 0 } },
3980 },
3981 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
3982 },
3983 .maximumnum = .{
3984 .ret_len = 1,
3985 .params = &.{
3986 .{ .kind = .overloaded },
3987 .{ .kind = .{ .matches = 0 } },
3988 .{ .kind = .{ .matches = 0 } },
3989 },
3990 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32053991 },
32063992 .copysign = .{
32073993 .ret_len = 1,
......@@ -3210,7 +3996,7 @@ pub const Intrinsic = enum {
32103996 .{ .kind = .{ .matches = 0 } },
32113997 .{ .kind = .{ .matches = 0 } },
32123998 },
3213 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3999 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32144000 },
32154001 .floor = .{
32164002 .ret_len = 1,
......@@ -3218,7 +4004,7 @@ pub const Intrinsic = enum {
32184004 .{ .kind = .overloaded },
32194005 .{ .kind = .{ .matches = 0 } },
32204006 },
3221 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4007 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32224008 },
32234009 .ceil = .{
32244010 .ret_len = 1,
......@@ -3226,7 +4012,7 @@ pub const Intrinsic = enum {
32264012 .{ .kind = .overloaded },
32274013 .{ .kind = .{ .matches = 0 } },
32284014 },
3229 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4015 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32304016 },
32314017 .trunc = .{
32324018 .ret_len = 1,
......@@ -3234,7 +4020,7 @@ pub const Intrinsic = enum {
32344020 .{ .kind = .overloaded },
32354021 .{ .kind = .{ .matches = 0 } },
32364022 },
3237 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4023 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32384024 },
32394025 .rint = .{
32404026 .ret_len = 1,
......@@ -3242,7 +4028,7 @@ pub const Intrinsic = enum {
32424028 .{ .kind = .overloaded },
32434029 .{ .kind = .{ .matches = 0 } },
32444030 },
3245 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4031 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32464032 },
32474033 .nearbyint = .{
32484034 .ret_len = 1,
......@@ -3250,7 +4036,7 @@ pub const Intrinsic = enum {
32504036 .{ .kind = .overloaded },
32514037 .{ .kind = .{ .matches = 0 } },
32524038 },
3253 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4039 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32544040 },
32554041 .round = .{
32564042 .ret_len = 1,
......@@ -3258,7 +4044,7 @@ pub const Intrinsic = enum {
32584044 .{ .kind = .overloaded },
32594045 .{ .kind = .{ .matches = 0 } },
32604046 },
3261 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4047 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32624048 },
32634049 .roundeven = .{
32644050 .ret_len = 1,
......@@ -3266,7 +4052,7 @@ pub const Intrinsic = enum {
32664052 .{ .kind = .overloaded },
32674053 .{ .kind = .{ .matches = 0 } },
32684054 },
3269 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4055 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32704056 },
32714057 .lround = .{
32724058 .ret_len = 1,
......@@ -3274,7 +4060,7 @@ pub const Intrinsic = enum {
32744060 .{ .kind = .overloaded },
32754061 .{ .kind = .overloaded },
32764062 },
3277 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4063 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32784064 },
32794065 .llround = .{
32804066 .ret_len = 1,
......@@ -3282,7 +4068,7 @@ pub const Intrinsic = enum {
32824068 .{ .kind = .overloaded },
32834069 .{ .kind = .overloaded },
32844070 },
3285 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4071 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32864072 },
32874073 .lrint = .{
32884074 .ret_len = 1,
......@@ -3290,7 +4076,7 @@ pub const Intrinsic = enum {
32904076 .{ .kind = .overloaded },
32914077 .{ .kind = .overloaded },
32924078 },
3293 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4079 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
32944080 },
32954081 .llrint = .{
32964082 .ret_len = 1,
......@@ -3298,7 +4084,7 @@ pub const Intrinsic = enum {
32984084 .{ .kind = .overloaded },
32994085 .{ .kind = .overloaded },
33004086 },
3301 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4087 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33024088 },
33034089
33044090 .bitreverse = .{
......@@ -3307,7 +4093,7 @@ pub const Intrinsic = enum {
33074093 .{ .kind = .overloaded },
33084094 .{ .kind = .{ .matches = 0 } },
33094095 },
3310 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4096 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33114097 },
33124098 .bswap = .{
33134099 .ret_len = 1,
......@@ -3315,7 +4101,7 @@ pub const Intrinsic = enum {
33154101 .{ .kind = .overloaded },
33164102 .{ .kind = .{ .matches = 0 } },
33174103 },
3318 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4104 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33194105 },
33204106 .ctpop = .{
33214107 .ret_len = 1,
......@@ -3323,7 +4109,7 @@ pub const Intrinsic = enum {
33234109 .{ .kind = .overloaded },
33244110 .{ .kind = .{ .matches = 0 } },
33254111 },
3326 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4112 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33274113 },
33284114 .ctlz = .{
33294115 .ret_len = 1,
......@@ -3332,7 +4118,7 @@ pub const Intrinsic = enum {
33324118 .{ .kind = .{ .matches = 0 } },
33334119 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
33344120 },
3335 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4121 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33364122 },
33374123 .cttz = .{
33384124 .ret_len = 1,
......@@ -3341,7 +4127,7 @@ pub const Intrinsic = enum {
33414127 .{ .kind = .{ .matches = 0 } },
33424128 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
33434129 },
3344 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4130 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33454131 },
33464132 .fshl = .{
33474133 .ret_len = 1,
......@@ -3351,7 +4137,7 @@ pub const Intrinsic = enum {
33514137 .{ .kind = .{ .matches = 0 } },
33524138 .{ .kind = .{ .matches = 0 } },
33534139 },
3354 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4140 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33554141 },
33564142 .fshr = .{
33574143 .ret_len = 1,
......@@ -3361,7 +4147,16 @@ pub const Intrinsic = enum {
33614147 .{ .kind = .{ .matches = 0 } },
33624148 .{ .kind = .{ .matches = 0 } },
33634149 },
3364 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4150 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
4151 },
4152 .clmul = .{
4153 .ret_len = 1,
4154 .params = &.{
4155 .{ .kind = .overloaded },
4156 .{ .kind = .{ .matches = 0 } },
4157 .{ .kind = .{ .matches = 0 } },
4158 },
4159 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33654160 },
33664161
33674162 .@"sadd.with.overflow" = .{
......@@ -3372,7 +4167,7 @@ pub const Intrinsic = enum {
33724167 .{ .kind = .{ .matches = 0 } },
33734168 .{ .kind = .{ .matches = 0 } },
33744169 },
3375 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4170 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33764171 },
33774172 .@"uadd.with.overflow" = .{
33784173 .ret_len = 2,
......@@ -3382,7 +4177,7 @@ pub const Intrinsic = enum {
33824177 .{ .kind = .{ .matches = 0 } },
33834178 .{ .kind = .{ .matches = 0 } },
33844179 },
3385 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4180 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33864181 },
33874182 .@"ssub.with.overflow" = .{
33884183 .ret_len = 2,
......@@ -3392,7 +4187,7 @@ pub const Intrinsic = enum {
33924187 .{ .kind = .{ .matches = 0 } },
33934188 .{ .kind = .{ .matches = 0 } },
33944189 },
3395 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4190 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
33964191 },
33974192 .@"usub.with.overflow" = .{
33984193 .ret_len = 2,
......@@ -3402,7 +4197,7 @@ pub const Intrinsic = enum {
34024197 .{ .kind = .{ .matches = 0 } },
34034198 .{ .kind = .{ .matches = 0 } },
34044199 },
3405 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4200 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34064201 },
34074202 .@"smul.with.overflow" = .{
34084203 .ret_len = 2,
......@@ -3412,7 +4207,7 @@ pub const Intrinsic = enum {
34124207 .{ .kind = .{ .matches = 0 } },
34134208 .{ .kind = .{ .matches = 0 } },
34144209 },
3415 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4210 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34164211 },
34174212 .@"umul.with.overflow" = .{
34184213 .ret_len = 2,
......@@ -3422,7 +4217,7 @@ pub const Intrinsic = enum {
34224217 .{ .kind = .{ .matches = 0 } },
34234218 .{ .kind = .{ .matches = 0 } },
34244219 },
3425 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4220 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34264221 },
34274222
34284223 .@"sadd.sat" = .{
......@@ -3432,7 +4227,7 @@ pub const Intrinsic = enum {
34324227 .{ .kind = .{ .matches = 0 } },
34334228 .{ .kind = .{ .matches = 0 } },
34344229 },
3435 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4230 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34364231 },
34374232 .@"uadd.sat" = .{
34384233 .ret_len = 1,
......@@ -3441,7 +4236,7 @@ pub const Intrinsic = enum {
34414236 .{ .kind = .{ .matches = 0 } },
34424237 .{ .kind = .{ .matches = 0 } },
34434238 },
3444 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4239 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34454240 },
34464241 .@"ssub.sat" = .{
34474242 .ret_len = 1,
......@@ -3450,7 +4245,7 @@ pub const Intrinsic = enum {
34504245 .{ .kind = .{ .matches = 0 } },
34514246 .{ .kind = .{ .matches = 0 } },
34524247 },
3453 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4248 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34544249 },
34554250 .@"usub.sat" = .{
34564251 .ret_len = 1,
......@@ -3459,7 +4254,7 @@ pub const Intrinsic = enum {
34594254 .{ .kind = .{ .matches = 0 } },
34604255 .{ .kind = .{ .matches = 0 } },
34614256 },
3462 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4257 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34634258 },
34644259 .@"sshl.sat" = .{
34654260 .ret_len = 1,
......@@ -3468,7 +4263,7 @@ pub const Intrinsic = enum {
34684263 .{ .kind = .{ .matches = 0 } },
34694264 .{ .kind = .{ .matches = 0 } },
34704265 },
3471 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4266 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34724267 },
34734268 .@"ushl.sat" = .{
34744269 .ret_len = 1,
......@@ -3477,7 +4272,7 @@ pub const Intrinsic = enum {
34774272 .{ .kind = .{ .matches = 0 } },
34784273 .{ .kind = .{ .matches = 0 } },
34794274 },
3480 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4275 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34814276 },
34824277
34834278 .@"smul.fix" = .{
......@@ -3488,7 +4283,7 @@ pub const Intrinsic = enum {
34884283 .{ .kind = .{ .matches = 0 } },
34894284 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
34904285 },
3491 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4286 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
34924287 },
34934288 .@"umul.fix" = .{
34944289 .ret_len = 1,
......@@ -3498,7 +4293,7 @@ pub const Intrinsic = enum {
34984293 .{ .kind = .{ .matches = 0 } },
34994294 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35004295 },
3501 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4296 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35024297 },
35034298 .@"smul.fix.sat" = .{
35044299 .ret_len = 1,
......@@ -3508,7 +4303,7 @@ pub const Intrinsic = enum {
35084303 .{ .kind = .{ .matches = 0 } },
35094304 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35104305 },
3511 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4306 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35124307 },
35134308 .@"umul.fix.sat" = .{
35144309 .ret_len = 1,
......@@ -3518,7 +4313,7 @@ pub const Intrinsic = enum {
35184313 .{ .kind = .{ .matches = 0 } },
35194314 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35204315 },
3521 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4316 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35224317 },
35234318 .@"sdiv.fix" = .{
35244319 .ret_len = 1,
......@@ -3528,7 +4323,7 @@ pub const Intrinsic = enum {
35284323 .{ .kind = .{ .matches = 0 } },
35294324 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35304325 },
3531 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4326 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35324327 },
35334328 .@"udiv.fix" = .{
35344329 .ret_len = 1,
......@@ -3538,7 +4333,7 @@ pub const Intrinsic = enum {
35384333 .{ .kind = .{ .matches = 0 } },
35394334 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35404335 },
3541 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4336 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35424337 },
35434338 .@"sdiv.fix.sat" = .{
35444339 .ret_len = 1,
......@@ -3548,7 +4343,7 @@ pub const Intrinsic = enum {
35484343 .{ .kind = .{ .matches = 0 } },
35494344 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35504345 },
3551 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4346 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35524347 },
35534348 .@"udiv.fix.sat" = .{
35544349 .ret_len = 1,
......@@ -3558,7 +4353,7 @@ pub const Intrinsic = enum {
35584353 .{ .kind = .{ .matches = 0 } },
35594354 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
35604355 },
3561 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4356 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
35624357 },
35634358
35644359 .canonicalize = .{
......@@ -3567,7 +4362,7 @@ pub const Intrinsic = enum {
35674362 .{ .kind = .overloaded },
35684363 .{ .kind = .{ .matches = 0 } },
35694364 },
3570 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4365 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35714366 },
35724367 .fmuladd = .{
35734368 .ret_len = 1,
......@@ -3577,7 +4372,7 @@ pub const Intrinsic = enum {
35774372 .{ .kind = .{ .matches = 0 } },
35784373 .{ .kind = .{ .matches = 0 } },
35794374 },
3580 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4375 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35814376 },
35824377
35834378 .@"vector.reduce.add" = .{
......@@ -3586,7 +4381,7 @@ pub const Intrinsic = enum {
35864381 .{ .kind = .{ .matches_scalar = 1 } },
35874382 .{ .kind = .overloaded },
35884383 },
3589 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4384 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35904385 },
35914386 .@"vector.reduce.fadd" = .{
35924387 .ret_len = 1,
......@@ -3595,7 +4390,7 @@ pub const Intrinsic = enum {
35954390 .{ .kind = .{ .matches_scalar = 2 } },
35964391 .{ .kind = .overloaded },
35974392 },
3598 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4393 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
35994394 },
36004395 .@"vector.reduce.mul" = .{
36014396 .ret_len = 1,
......@@ -3603,7 +4398,7 @@ pub const Intrinsic = enum {
36034398 .{ .kind = .{ .matches_scalar = 1 } },
36044399 .{ .kind = .overloaded },
36054400 },
3606 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4401 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36074402 },
36084403 .@"vector.reduce.fmul" = .{
36094404 .ret_len = 1,
......@@ -3612,7 +4407,7 @@ pub const Intrinsic = enum {
36124407 .{ .kind = .{ .matches_scalar = 2 } },
36134408 .{ .kind = .overloaded },
36144409 },
3615 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4410 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36164411 },
36174412 .@"vector.reduce.and" = .{
36184413 .ret_len = 1,
......@@ -3620,7 +4415,7 @@ pub const Intrinsic = enum {
36204415 .{ .kind = .{ .matches_scalar = 1 } },
36214416 .{ .kind = .overloaded },
36224417 },
3623 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4418 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36244419 },
36254420 .@"vector.reduce.or" = .{
36264421 .ret_len = 1,
......@@ -3628,7 +4423,7 @@ pub const Intrinsic = enum {
36284423 .{ .kind = .{ .matches_scalar = 1 } },
36294424 .{ .kind = .overloaded },
36304425 },
3631 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4426 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36324427 },
36334428 .@"vector.reduce.xor" = .{
36344429 .ret_len = 1,
......@@ -3636,7 +4431,7 @@ pub const Intrinsic = enum {
36364431 .{ .kind = .{ .matches_scalar = 1 } },
36374432 .{ .kind = .overloaded },
36384433 },
3639 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4434 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36404435 },
36414436 .@"vector.reduce.smax" = .{
36424437 .ret_len = 1,
......@@ -3644,7 +4439,7 @@ pub const Intrinsic = enum {
36444439 .{ .kind = .{ .matches_scalar = 1 } },
36454440 .{ .kind = .overloaded },
36464441 },
3647 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4442 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36484443 },
36494444 .@"vector.reduce.smin" = .{
36504445 .ret_len = 1,
......@@ -3652,7 +4447,7 @@ pub const Intrinsic = enum {
36524447 .{ .kind = .{ .matches_scalar = 1 } },
36534448 .{ .kind = .overloaded },
36544449 },
3655 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4450 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36564451 },
36574452 .@"vector.reduce.umax" = .{
36584453 .ret_len = 1,
......@@ -3660,7 +4455,7 @@ pub const Intrinsic = enum {
36604455 .{ .kind = .{ .matches_scalar = 1 } },
36614456 .{ .kind = .overloaded },
36624457 },
3663 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4458 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36644459 },
36654460 .@"vector.reduce.umin" = .{
36664461 .ret_len = 1,
......@@ -3668,7 +4463,7 @@ pub const Intrinsic = enum {
36684463 .{ .kind = .{ .matches_scalar = 1 } },
36694464 .{ .kind = .overloaded },
36704465 },
3671 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4466 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36724467 },
36734468 .@"vector.reduce.fmax" = .{
36744469 .ret_len = 1,
......@@ -3676,7 +4471,7 @@ pub const Intrinsic = enum {
36764471 .{ .kind = .{ .matches_scalar = 1 } },
36774472 .{ .kind = .overloaded },
36784473 },
3679 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4474 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36804475 },
36814476 .@"vector.reduce.fmin" = .{
36824477 .ret_len = 1,
......@@ -3684,7 +4479,7 @@ pub const Intrinsic = enum {
36844479 .{ .kind = .{ .matches_scalar = 1 } },
36854480 .{ .kind = .overloaded },
36864481 },
3687 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4482 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36884483 },
36894484 .@"vector.reduce.fmaximum" = .{
36904485 .ret_len = 1,
......@@ -3692,7 +4487,7 @@ pub const Intrinsic = enum {
36924487 .{ .kind = .{ .matches_scalar = 1 } },
36934488 .{ .kind = .overloaded },
36944489 },
3695 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4490 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
36964491 },
36974492 .@"vector.reduce.fminimum" = .{
36984493 .ret_len = 1,
......@@ -3700,7 +4495,7 @@ pub const Intrinsic = enum {
37004495 .{ .kind = .{ .matches_scalar = 1 } },
37014496 .{ .kind = .overloaded },
37024497 },
3703 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4498 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37044499 },
37054500 .@"vector.insert" = .{
37064501 .ret_len = 1,
......@@ -3710,7 +4505,7 @@ pub const Intrinsic = enum {
37104505 .{ .kind = .overloaded },
37114506 .{ .kind = .{ .type = .i64 } },
37124507 },
3713 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4508 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37144509 },
37154510 .@"vector.extract" = .{
37164511 .ret_len = 1,
......@@ -3719,7 +4514,7 @@ pub const Intrinsic = enum {
37194514 .{ .kind = .overloaded },
37204515 .{ .kind = .{ .type = .i64 } },
37214516 },
3722 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4517 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37234518 },
37244519
37254520 .@"is.fpclass" = .{
......@@ -3729,7 +4524,7 @@ pub const Intrinsic = enum {
37294524 .{ .kind = .overloaded },
37304525 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
37314526 },
3732 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4527 .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
37334528 },
37344529
37354530 .@"var.annotation" = .{
......@@ -3814,7 +4609,7 @@ pub const Intrinsic = enum {
38144609 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
38154610 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
38164611 },
3817 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4612 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
38184613 },
38194614 .expect = .{
38204615 .ret_len = 1,
......@@ -3823,7 +4618,7 @@ pub const Intrinsic = enum {
38234618 .{ .kind = .{ .matches = 0 } },
38244619 .{ .kind = .{ .matches = 0 } },
38254620 },
3826 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4621 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38274622 },
38284623 .@"expect.with.probability" = .{
38294624 .ret_len = 1,
......@@ -3833,7 +4628,7 @@ pub const Intrinsic = enum {
38334628 .{ .kind = .{ .matches = 0 } },
38344629 .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} },
38354630 },
3836 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4631 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38374632 },
38384633 .assume = .{
38394634 .ret_len = 0,
......@@ -3848,7 +4643,7 @@ pub const Intrinsic = enum {
38484643 .{ .kind = .overloaded },
38494644 .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} },
38504645 },
3851 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4646 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38524647 },
38534648 .@"type.test" = .{
38544649 .ret_len = 1,
......@@ -3857,7 +4652,7 @@ pub const Intrinsic = enum {
38574652 .{ .kind = .{ .type = .ptr } },
38584653 .{ .kind = .{ .type = .metadata } },
38594654 },
3860 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4655 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
38614656 },
38624657 .@"type.checked.load" = .{
38634658 .ret_len = 2,
......@@ -3868,7 +4663,7 @@ pub const Intrinsic = enum {
38684663 .{ .kind = .{ .type = .i32 } },
38694664 .{ .kind = .{ .type = .metadata } },
38704665 },
3871 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4666 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38724667 },
38734668 .@"type.checked.load.relative" = .{
38744669 .ret_len = 2,
......@@ -3879,7 +4674,7 @@ pub const Intrinsic = enum {
38794674 .{ .kind = .{ .type = .i32 } },
38804675 .{ .kind = .{ .type = .metadata } },
38814676 },
3882 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4677 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38834678 },
38844679 .@"arithmetic.fence" = .{
38854680 .ret_len = 1,
......@@ -3887,12 +4682,12 @@ pub const Intrinsic = enum {
38874682 .{ .kind = .overloaded },
38884683 .{ .kind = .{ .matches = 0 } },
38894684 },
3890 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4685 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
38914686 },
38924687 .donothing = .{
38934688 .ret_len = 0,
38944689 .params = &.{},
3895 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4690 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
38964691 },
38974692 .@"load.relative" = .{
38984693 .ret_len = 1,
......@@ -3914,7 +4709,7 @@ pub const Intrinsic = enum {
39144709 .{ .kind = .{ .type = .i1 } },
39154710 .{ .kind = .overloaded },
39164711 },
3917 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4712 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
39184713 },
39194714 .ptrmask = .{
39204715 .ret_len = 1,
......@@ -3923,7 +4718,7 @@ pub const Intrinsic = enum {
39234718 .{ .kind = .{ .matches = 0 } },
39244719 .{ .kind = .overloaded },
39254720 },
3926 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4721 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39274722 },
39284723 .@"threadlocal.address" = .{
39294724 .ret_len = 1,
......@@ -3931,14 +4726,14 @@ pub const Intrinsic = enum {
39314726 .{ .kind = .overloaded, .attrs = &.{.nonnull} },
39324727 .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} },
39334728 },
3934 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4729 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39354730 },
39364731 .vscale = .{
39374732 .ret_len = 1,
39384733 .params = &.{
39394734 .{ .kind = .overloaded },
39404735 },
3941 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4736 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
39424737 },
39434738
39444739 .@"dbg.declare" = .{
......@@ -3948,7 +4743,7 @@ pub const Intrinsic = enum {
39484743 .{ .kind = .{ .type = .metadata } },
39494744 .{ .kind = .{ .type = .metadata } },
39504745 },
3951 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4746 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39524747 },
39534748 .@"dbg.value" = .{
39544749 .ret_len = 0,
......@@ -3957,7 +4752,7 @@ pub const Intrinsic = enum {
39574752 .{ .kind = .{ .type = .metadata } },
39584753 .{ .kind = .{ .type = .metadata } },
39594754 },
3960 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4755 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39614756 },
39624757
39634758 .@"amdgcn.workitem.id.x" = .{
......@@ -3965,42 +4760,42 @@ pub const Intrinsic = enum {
39654760 .params = &.{
39664761 .{ .kind = .{ .type = .i32 } },
39674762 },
3968 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4763 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39694764 },
39704765 .@"amdgcn.workitem.id.y" = .{
39714766 .ret_len = 1,
39724767 .params = &.{
39734768 .{ .kind = .{ .type = .i32 } },
39744769 },
3975 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4770 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39764771 },
39774772 .@"amdgcn.workitem.id.z" = .{
39784773 .ret_len = 1,
39794774 .params = &.{
39804775 .{ .kind = .{ .type = .i32 } },
39814776 },
3982 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4777 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39834778 },
39844779 .@"amdgcn.workgroup.id.x" = .{
39854780 .ret_len = 1,
39864781 .params = &.{
39874782 .{ .kind = .{ .type = .i32 } },
39884783 },
3989 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4784 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39904785 },
39914786 .@"amdgcn.workgroup.id.y" = .{
39924787 .ret_len = 1,
39934788 .params = &.{
39944789 .{ .kind = .{ .type = .i32 } },
39954790 },
3996 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4791 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
39974792 },
39984793 .@"amdgcn.workgroup.id.z" = .{
39994794 .ret_len = 1,
40004795 .params = &.{
40014796 .{ .kind = .{ .type = .i32 } },
40024797 },
4003 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4798 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
40044799 },
40054800 .@"amdgcn.dispatch.ptr" = .{
40064801 .ret_len = 1,
......@@ -4010,7 +4805,7 @@ pub const Intrinsic = enum {
40104805 .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }},
40114806 },
40124807 },
4013 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4808 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } },
40144809 },
40154810
40164811 .@"nvvm.read.ptx.sreg.tid.x" = .{
......@@ -4085,7 +4880,7 @@ pub const Intrinsic = enum {
40854880 .{ .kind = .overloaded },
40864881 .{ .kind = .{ .type = .i32 } },
40874882 },
4088 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
4883 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } },
40894884 },
40904885 .@"wasm.memory.grow" = .{
40914886 .ret_len = 1,
......@@ -4166,6 +4961,10 @@ pub const Function = struct {
41664961 self.ptr(builder).attributes = new_function_attributes;
41674962 }
41684963
4964 pub fn getAttributes(self: Index, builder: *Builder) FunctionAttributes {
4965 return self.ptr(builder).attributes;
4966 }
4967
41694968 pub fn setSection(self: Index, section: String, builder: *Builder) void {
41704969 self.ptr(builder).section = section;
41714970 }
......@@ -4487,7 +5286,7 @@ pub const Function = struct {
44875286 }
44885287
44895288 pub fn toValue(self: Instruction.Index) Value {
4490 return @fromBackingInt(@intCast(@backingInt(self)));
5289 return @fromBackingInt(@backingInt(self));
44915290 }
44925291
44935292 pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool {
......@@ -4679,7 +5478,7 @@ pub const Function = struct {
46795478 .changeScalarAssumeCapacity(.i1, wip.builder),
46805479 .fneg,
46815480 .@"fneg fast",
4682 => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOfWip(wip),
5481 => @as(Value, @fromBackingInt(instruction.data)).typeOfWip(wip),
46835482 .getelementptr,
46845483 .@"getelementptr inbounds",
46855484 => {
......@@ -4871,7 +5670,7 @@ pub const Function = struct {
48715670 .changeScalarAssumeCapacity(.i1, builder),
48725671 .fneg,
48735672 .@"fneg fast",
4874 => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOf(function_index, builder),
5673 => @as(Value, @fromBackingInt(instruction.data)).typeOf(function_index, builder),
48755674 .getelementptr,
48765675 .@"getelementptr inbounds",
48775676 => {
......@@ -4963,7 +5762,7 @@ pub const Function = struct {
49635762
49645763 pub fn fromMetadata(metadata: Metadata) Weights {
49655764 assert(metadata.kind == .node);
4966 return @fromBackingInt(@intCast(metadata.index));
5765 return @fromBackingInt(metadata.index);
49675766 }
49685767
49695768 pub fn toMetadata(weights: Weights) Metadata {
......@@ -5156,7 +5955,7 @@ pub const Function = struct {
51565955 assert(argument.tag == .arg);
51575956 assert(argument.data == index);
51585957
5159 const argument_index: Instruction.Index = @fromBackingInt(@intCast(index));
5958 const argument_index: Instruction.Index = @fromBackingInt(index);
51605959 return argument_index.toValue();
51615960 }
51625961
......@@ -5202,7 +6001,7 @@ pub const Function = struct {
52026001 Type,
52036002 Value,
52046003 Instruction.BrCond.Weights,
5205 => @fromBackingInt(@intCast(value)),
6004 => @fromBackingInt(value),
52066005 MemoryAccessInfo,
52076006 Instruction.Alloca.Info,
52086007 Instruction.Call.Info,
......@@ -5327,7 +6126,7 @@ pub const WipFunction = struct {
53276126 assert(argument.tag == .arg);
53286127 assert(argument.data == index);
53296128
5330 const argument_index: Instruction.Index = @fromBackingInt(@intCast(index));
6129 const argument_index: Instruction.Index = @fromBackingInt(index);
53316130 return argument_index.toValue();
53326131 }
53336132
......@@ -5722,7 +6521,7 @@ pub const WipFunction = struct {
57226521 alignment: Alignment,
57236522 name: []const u8,
57246523 ) Allocator.Error!Value {
5725 return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name);
6524 return self.loadAtomic(access_kind, ty, ptr, undefined, .none, alignment, name);
57266525 }
57276526
57286527 pub fn loadAtomic(
......@@ -5766,7 +6565,7 @@ pub const WipFunction = struct {
57666565 ptr: Value,
57676566 alignment: Alignment,
57686567 ) Allocator.Error!Instruction.Index {
5769 return self.storeAtomic(kind, val, ptr, .system, .none, alignment);
6568 return self.storeAtomic(kind, val, ptr, undefined, .none, alignment);
57706569 }
57716570
57726571 pub fn storeAtomic(
......@@ -6414,24 +7213,24 @@ pub const WipFunction = struct {
64147213 errdefer function.instructions.shrinkRetainingCapacity(0);
64157214
64167215 {
6417 var final_instruction_index: Instruction.Index = @fromBackingInt(@intCast(0));
7216 var final_instruction_index: Instruction.Index = @fromBackingInt(0);
64187217 for (0..params_len) |param_index| {
64197218 instructions.items[param_index] = final_instruction_index;
6420 final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1));
7219 final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1);
64217220 }
64227221 for (blocks, self.blocks.items) |*final_block, current_block| {
64237222 assert(current_block.incoming == current_block.branches);
64247223 final_block.instruction = final_instruction_index;
6425 final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1));
7224 final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1);
64267225 for (current_block.instructions.items) |instruction| {
64277226 instructions.items[@backingInt(instruction)] = final_instruction_index;
6428 final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1));
7227 final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1);
64297228 }
64307229 }
64317230 }
64327231
64337232 var wip_name: struct {
6434 next_name: String = @fromBackingInt(@intCast(0)),
7233 next_name: String = @fromBackingInt(0),
64357234 next_unique_name: std.AutoHashMap(String, String),
64367235 builder: *Builder,
64377236
......@@ -6440,19 +7239,19 @@ pub const WipFunction = struct {
64407239 .none => return .none,
64417240 .empty => {
64427241 assert(wip_name.next_name != .none);
6443 defer wip_name.next_name = @fromBackingInt(@intCast(@backingInt(wip_name.next_name) + 1));
7242 defer wip_name.next_name = @fromBackingInt(@backingInt(wip_name.next_name) + 1);
64447243 return wip_name.next_name;
64457244 },
64467245 _ => {
64477246 assert(!name.isAnon());
64487247 const gop = try wip_name.next_unique_name.getOrPut(name);
64497248 if (!gop.found_existing) {
6450 gop.value_ptr.* = @fromBackingInt(@intCast(0));
7249 gop.value_ptr.* = @fromBackingInt(0);
64517250 return name;
64527251 }
64537252
64547253 while (true) {
6455 gop.value_ptr.* = @fromBackingInt(@intCast(@backingInt(gop.value_ptr.*) + 1));
7254 gop.value_ptr.* = @fromBackingInt(@backingInt(gop.value_ptr.*) + 1);
64567255 const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{
64577256 name.fmtRaw(wip_name.builder),
64587257 sep,
......@@ -6460,7 +7259,7 @@ pub const WipFunction = struct {
64607259 });
64617260 const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);
64627261 if (!unique_gop.found_existing) {
6463 unique_gop.value_ptr.* = @fromBackingInt(@intCast(0));
7262 unique_gop.value_ptr.* = @fromBackingInt(0);
64647263 return unique_name;
64657264 }
64667265 }
......@@ -6702,7 +7501,7 @@ pub const WipFunction = struct {
67027501 .fneg,
67037502 .@"fneg fast",
67047503 .ret,
6705 => instruction.data = @backingInt(instructions.map(@fromBackingInt(@intCast(instruction.data)))),
7504 => instruction.data = @backingInt(instructions.map(@fromBackingInt(instruction.data))),
67067505 .getelementptr,
67077506 .@"getelementptr inbounds",
67087507 => {
......@@ -7079,7 +7878,7 @@ pub const WipFunction = struct {
70797878 Type,
70807879 Value,
70817880 Instruction.BrCond.Weights,
7082 => @fromBackingInt(@intCast(value)),
7881 => @fromBackingInt(value),
70837882 MemoryAccessInfo,
70847883 Instruction.Alloca.Info,
70857884 Instruction.Call.Info,
......@@ -7268,7 +8067,7 @@ pub const Constant = enum(u32) {
72688067 no_init = (1 << 30) - 1,
72698068 _,
72708069
7271 const first_global: Constant = @fromBackingInt(@intCast(1 << 29));
8070 const first_global: Constant = @fromBackingInt(1 << 29);
72728071
72738072 pub const Tag = enum(u7) {
72748073 positive_integer,
......@@ -7405,7 +8204,18 @@ pub const Constant = enum(u32) {
74058204 val: Constant,
74068205 type: Type,
74078206
7408 pub const Signedness = enum { unsigned, signed, unneeded };
8207 pub const Signedness = enum {
8208 unsigned,
8209 signed,
8210 unneeded,
8211
8212 pub fn fromStdLang(signedness: std.lang.Signedness) Signedness {
8213 return switch (signedness) {
8214 .unsigned => .unsigned,
8215 .signed => .signed,
8216 };
8217 }
8218 };
74098219 };
74108220
74118221 pub const GetElementPtr = struct {
......@@ -7444,11 +8254,11 @@ pub const Constant = enum(u32) {
74448254 return if (@backingInt(self) < @backingInt(first_global))
74458255 .{ .constant = @intCast(@backingInt(self)) }
74468256 else
7447 .{ .global = @fromBackingInt(@intCast(@backingInt(self) - @backingInt(first_global))) };
8257 .{ .global = @fromBackingInt(@backingInt(self) - @backingInt(first_global)) };
74488258 }
74498259
74508260 pub fn toValue(self: Constant) Value {
7451 return @fromBackingInt(@intCast(Value.first_constant + @backingInt(self)));
8261 return @fromBackingInt(Value.first_constant + @backingInt(self));
74528262 }
74538263
74548264 pub fn typeOf(self: Constant, builder: *Builder) Type {
......@@ -7474,7 +8284,7 @@ pub const Constant = enum(u32) {
74748284 .zeroinitializer,
74758285 .undef,
74768286 .poison,
7477 => @fromBackingInt(@intCast(item.data)),
8287 => @fromBackingInt(item.data),
74788288 .structure,
74798289 .packed_structure,
74808290 .array,
......@@ -7482,7 +8292,7 @@ pub const Constant = enum(u32) {
74828292 => builder.constantExtraData(Aggregate, item.data).type,
74838293 .splat => builder.constantExtraData(Splat, item.data).type,
74848294 .string => builder.arrayTypeAssumeCapacity(
7485 @as(String, @fromBackingInt(@intCast(item.data))).slice(builder).?.len,
8295 @as(String, @fromBackingInt(item.data)).slice(builder).?.len,
74868296 .i8,
74878297 ),
74888298 .blockaddress => builder.ptrTypeAssumeCapacity(
......@@ -7491,7 +8301,7 @@ pub const Constant = enum(u32) {
74918301 ),
74928302 .dso_local_equivalent,
74938303 .no_cfi,
7494 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(@intCast(item.data)))
8304 => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(item.data))
74958305 .ptrConst(builder).global.ptrConst(builder).addr_space),
74968306 .trunc,
74978307 .ptrtoint,
......@@ -7802,7 +8612,7 @@ pub const Constant = enum(u32) {
78028612 try w.writeByte('>');
78038613 },
78048614 .string => try w.print("c{f}", .{
7805 @as(String, @fromBackingInt(@intCast(item.data))).fmtQ(data.builder),
8615 @as(String, @fromBackingInt(item.data)).fmtQ(data.builder),
78068616 }),
78078617 .blockaddress => |tag| {
78088618 const extra = data.builder.constantExtraData(BlockAddress, item.data);
......@@ -7816,7 +8626,7 @@ pub const Constant = enum(u32) {
78168626 .dso_local_equivalent,
78178627 .no_cfi,
78188628 => |tag| {
7819 const function: Function.Index = @fromBackingInt(@intCast(item.data));
8629 const function: Function.Index = @fromBackingInt(item.data);
78208630 try w.print("{s} {f}", .{
78218631 @tagName(tag),
78228632 function.ptrConst(data.builder).global.fmt(data.builder),
......@@ -7920,9 +8730,9 @@ pub const Value = enum(u32) {
79208730 metadata: Metadata,
79218731 } {
79228732 return if (@backingInt(self) < first_constant)
7923 .{ .instruction = @fromBackingInt(@intCast(@backingInt(self))) }
8733 .{ .instruction = @fromBackingInt(@backingInt(self)) }
79248734 else if (@backingInt(self) < first_metadata)
7925 .{ .constant = @fromBackingInt(@intCast(@backingInt(self) - first_constant)) }
8735 .{ .constant = @fromBackingInt(@backingInt(self) - first_constant) }
79268736 else
79278737 .{ .metadata = @bitCast(@backingInt(self) - first_metadata) };
79288738 }
......@@ -8016,7 +8826,7 @@ pub const Metadata = packed struct(u32) {
80168826 return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false };
80178827 }
80188828 pub fn toValue(metadata: Metadata) Value {
8019 return @fromBackingInt(@intCast(Value.first_metadata + @as(u32, @bitCast(metadata))));
8829 return @fromBackingInt(Value.first_metadata + @as(u32, @bitCast(metadata)));
80208830 }
80218831
80228832 pub const String = enum(u32) {
......@@ -8032,7 +8842,7 @@ pub const Metadata = packed struct(u32) {
80328842 pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String {
80338843 return switch (metadata) {
80348844 .none => null,
8035 else => @fromBackingInt(@intCast(@backingInt(metadata))),
8845 else => @fromBackingInt(@backingInt(metadata)),
80368846 };
80378847 }
80388848 pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional {
......@@ -8040,7 +8850,7 @@ pub const Metadata = packed struct(u32) {
80408850 }
80418851 };
80428852 pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional {
8043 return @fromBackingInt(@intCast(@backingInt(metadata)));
8853 return @fromBackingInt(@backingInt(metadata));
80448854 }
80458855 pub fn toMetadata(metadata: Metadata.String) Metadata {
80468856 return .{ .index = @intCast(@backingInt(metadata)), .kind = .string };
......@@ -8077,7 +8887,7 @@ pub const Metadata = packed struct(u32) {
80778887 };
80788888 pub fn toString(metadata: Metadata) Metadata.String {
80798889 assert(metadata.kind == .string);
8080 return @fromBackingInt(@intCast(metadata.index));
8890 return @fromBackingInt(metadata.index);
80818891 }
80828892
80838893 pub const Tag = enum(u6) {
......@@ -8542,7 +9352,7 @@ pub const Metadata = packed struct(u32) {
85429352 try w.writeByte(')');
85439353 },
85449354 .constant => try Constant.format(.{
8545 .constant = @fromBackingInt(@intCast(node_item.data)),
9355 .constant = @fromBackingInt(node_item.data),
85469356 .builder = builder,
85479357 .flags = data.specialized orelse .{},
85489358 }, w),
......@@ -8735,7 +9545,14 @@ pub fn init(options: Options) Allocator.Error!Builder {
87359545 .strip = options.strip,
87369546
87379547 .source_filename = .none,
8738 .data_layout = .none,
9548 .data_layout = .{
9549 .endian = null,
9550 .int_specs = .empty,
9551 .float_specs = .empty,
9552 .vector_specs = .empty,
9553 .pointer_specs = .empty,
9554 .string_repr = .none,
9555 },
87399556 .target_triple = .none,
87409557 .module_asm = .empty,
87419558
......@@ -8744,7 +9561,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
87449561 .string_bytes = .empty,
87459562
87469563 .types = .empty,
8747 .next_unnamed_type = @fromBackingInt(@intCast(0)),
9564 .next_unnamed_type = @fromBackingInt(0),
87489565 .next_unique_type_id = .empty,
87499566 .type_map = .empty,
87509567 .type_items = .empty,
......@@ -8758,7 +9575,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
87589575 .function_attributes_set = .empty,
87599576
87609577 .globals = .empty,
8761 .next_unnamed_global = @fromBackingInt(@intCast(0)),
9578 .next_unnamed_global = @fromBackingInt(0),
87629579 .next_replaced_global = .none,
87639580 .next_unique_global_id = .empty,
87649581 .aliases = .empty,
......@@ -8791,14 +9608,14 @@ pub fn init(options: Options) Allocator.Error!Builder {
87919608 try self.string_indices.append(self.gpa, 0);
87929609 assert(try self.string("") == .empty);
87939610
9611 self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self);
9612
87949613 try self.strtab_string_indices.append(self.gpa, 0);
87959614 assert(try self.strtabString("") == .empty);
87969615
87979616 if (options.name.len > 0) self.source_filename = try self.string(options.name);
87989617
8799 if (options.triple.len > 0) {
8800 self.target_triple = try self.string(options.triple);
8801 }
9618 if (options.triple.len > 0) self.target_triple = try self.string(options.triple);
88029619
88039620 {
88049621 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;
......@@ -8815,7 +9632,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
88159632 assert(self.intTypeAssumeCapacity(bits) ==
88169633 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
88179634 inline for (.{ 0, 4 }) |addr_space_index| {
8818 const addr_space: AddrSpace = @fromBackingInt(@intCast(addr_space_index));
9635 const addr_space: AddrSpace = @fromBackingInt(addr_space_index);
88199636 assert(self.ptrTypeAssumeCapacity(addr_space) ==
88209637 @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")})));
88219638 }
......@@ -8891,6 +9708,8 @@ pub fn clearAndFree(self: *Builder) void {
88919708pub fn deinit(self: *Builder) void {
88929709 const gpa = self.gpa;
88939710
9711 self.data_layout.deinit(gpa);
9712
88949713 self.module_asm.deinit(gpa);
88959714
88969715 self.string_map.deinit(gpa);
......@@ -9092,17 +9911,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr
90929911 return @backingInt(lhs_kind) < @backingInt(rhs_kind);
90939912 }
90949913 }.lessThan);
9095 return @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(attributes))));
9914 return @fromBackingInt(try self.attrGeneric(@ptrCast(attributes)));
90969915}
90979916
90989917pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {
90999918 try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1);
9100 const function_attributes: FunctionAttributes = @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(
9919 const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast(
91019920 fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last|
91029921 last + 1
91039922 else
91049923 0],
9105 ))));
9924 )));
91069925
91079926 _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes);
91089927 return function_attributes;
......@@ -9121,7 +9940,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa
91219940 if (name == .empty) {
91229941 id = self.next_unnamed_global;
91239942 assert(id != self.next_replaced_global);
9124 self.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(id) + 1));
9943 self.next_unnamed_global = @fromBackingInt(@backingInt(id) + 1);
91259944 }
91269945 while (true) {
91279946 const global_gop = self.globals.getOrPutAssumeCapacity(id);
......@@ -9710,17 +10529,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
971010529 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
971110530 defer metadata_formatter.map.deinit(self.gpa);
971210531
9713 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
10532 if (self.source_filename != .none or self.data_layout.string_repr != .none or self.target_triple != .none) {
971410533 if (need_newline) try w.writeByte('\n') else need_newline = true;
971510534 if (self.source_filename != .none) try w.print(
971610535 \\; ModuleID = '{s}'
971710536 \\source_filename = {f}
971810537 \\
971910538 , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) });
9720 if (self.data_layout != .none) try w.print(
10539 if (self.data_layout.string_repr != .none) try w.print(
972110540 \\target datalayout = {f}
972210541 \\
9723 , .{self.data_layout.fmtQ(self)});
10542 , .{self.data_layout.string_repr.fmtQ(self)});
972410543 if (self.target_triple != .none) try w.print(
972510544 \\target triple = {f}
972610545 \\
......@@ -10058,7 +10877,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
1005810877 continue;
1005910878 },
1006010879 .br => |tag| {
10061 const target: Function.Block.Index = @fromBackingInt(@intCast(instruction.data));
10880 const target: Function.Block.Index = @fromBackingInt(instruction.data);
1006210881 try w.print(" {s} {f}", .{
1006310882 @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }),
1006410883 });
......@@ -10187,7 +11006,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
1018711006 .fneg,
1018811007 .@"fneg fast",
1018911008 => |tag| {
10190 const val: Value = @fromBackingInt(@intCast(instruction.data));
11009 const val: Value = @fromBackingInt(instruction.data);
1019111010 try w.print(" %{f} = {s} {f}", .{
1019211011 instruction_index.name(&function).fmt(self),
1019311012 @tagName(tag),
......@@ -10288,7 +11107,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
1028811107 }
1028911108 },
1029011109 .ret => |tag| {
10291 const val: Value = @fromBackingInt(@intCast(instruction.data));
11110 const val: Value = @fromBackingInt(instruction.data);
1029211111 try w.print(" {s} {f}", .{
1029311112 @tagName(tag),
1029411113 val.fmt(function_index, self, .{ .percent = true }),
......@@ -11020,7 +11839,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
1102011839 if (name == .empty) {
1102111840 id = self.next_unnamed_type;
1102211841 assert(id != .none);
11023 self.next_unnamed_type = @fromBackingInt(@intCast(@backingInt(id) + 1));
11842 self.next_unnamed_type = @fromBackingInt(@backingInt(id) + 1);
1102411843 } else assert(!name.isAnon());
1102511844 while (true) {
1102611845 const type_gop = self.types.getOrPutAssumeCapacity(id);
......@@ -11135,7 +11954,7 @@ fn typeExtraDataTrail(
1113511954 ) |field_name, field_type, value|
1113611955 @field(result, field_name) = switch (field_type) {
1113711956 u32 => value,
11138 String, Type => @fromBackingInt(@intCast(value)),
11957 String, Type => @fromBackingInt(value),
1113911958 else => @compileError("bad field type: " ++ @typeName(field_type)),
1114011959 };
1114111960 return .{
......@@ -11746,7 +12565,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty:
1174612565 return std.meta.eql(lhs_key.cast, rhs_extra);
1174712566 }
1174812567 };
11749 const data = Key{ .tag = tag, .cast = .{ .val = val, .type = ty } };
12568 const data: Key = .{ .tag = tag, .cast = .{ .val = val, .type = ty } };
1175012569 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1175112570 if (!gop.found_existing) {
1175212571 gop.key_ptr.* = {};
......@@ -11828,10 +12647,10 @@ fn gepConstAssumeCapacity(
1182812647 std.mem.eql(Constant, lhs_key.indices, rhs_indices);
1182912648 }
1183012649 };
11831 const data = Key{
12650 const data: Key = .{
1183212651 .type = ty,
1183312652 .base = base,
11834 .inrange = if (inrange) |index| @fromBackingInt(@intCast(index)) else .none,
12653 .inrange = if (inrange) |index| @fromBackingInt(index) else .none,
1183512654 .indices = indices,
1183612655 };
1183712656 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
......@@ -11885,7 +12704,7 @@ fn binConstAssumeCapacity(
1188512704 return std.meta.eql(lhs_key.extra, rhs_extra);
1188612705 }
1188712706 };
11888 const data = Key{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } };
12707 const data: Key = .{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } };
1188912708 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1189012709 if (!gop.found_existing) {
1189112710 gop.key_ptr.* = {};
......@@ -11924,8 +12743,8 @@ fn asmConstAssumeCapacity(
1192412743 }
1192512744 };
1192612745
11927 const data = Key{
11928 .tag = @fromBackingInt(@intCast(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info)))),
12746 const data: Key = .{
12747 .tag = @fromBackingInt(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info))),
1192912748 .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints },
1193012749 };
1193112750 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
......@@ -12073,7 +12892,7 @@ fn constantExtraDataTrail(
1207312892 ) |field_name, field_type, value|
1207412893 @field(result, field_name) = switch (field_type) {
1207512894 u32 => value,
12076 String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(@intCast(value)),
12895 String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(value),
1207712896 Constant.GetElementPtr.Info => @bitCast(value),
1207812897 else => @compileError("bad field type: " ++ @typeName(field_type)),
1207912898 };
......@@ -12151,7 +12970,7 @@ fn metadataExtraDataTrail(
1215112970 ) |field_name, field_type, value|
1215212971 @field(result, field_name) = switch (field_type) {
1215312972 u32 => value,
12154 Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(@intCast(value)),
12973 Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(value),
1215512974 Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value),
1215612975 else => @compileError("bad field type: " ++ @typeName(field_type)),
1215712976 };
......@@ -12759,8 +13578,8 @@ fn debugSubprogramAssumeCapacity(
1275913578 compile_unit: ?Metadata,
1276013579) Metadata {
1276113580 assert(!self.strip);
12762 const tag: Metadata.Tag = @fromBackingInt(@intCast(@backingInt(Metadata.Tag.subprogram) +
12763 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))));
13581 const tag: Metadata.Tag = @fromBackingInt(@backingInt(Metadata.Tag.subprogram) +
13582 @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)));
1276413583 return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{
1276513584 .file = .wrap(file),
1276613585 .name = .wrap(name),
......@@ -13345,7 +14164,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {
1334514164
1334614165 pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool {
1334714166 if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13348 const rhs_data: Constant = @fromBackingInt(@intCast(ctx.builder.metadata_items.items(.data)[rhs_index]));
14167 const rhs_data: Constant = @fromBackingInt(ctx.builder.metadata_items.items(.data)[rhs_index]);
1334914168 return rhs_data == lhs_key;
1335014169 }
1335114170 };
......@@ -13418,7 +14237,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1341814237 });
1341914238 }
1342014239
13421 if (self.data_layout.slice(self)) |data_layout| {
14240 if (self.data_layout.string_repr.slice(self)) |data_layout| {
1342214241 try module_block.writeAbbrev(ModuleBlock.String{
1342314242 .code = 3,
1342414243 .string = data_layout,
......@@ -13577,6 +14396,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1357714396 switch (attr_index.toAttribute(self)) {
1357814397 .zeroext,
1357914398 .signext,
14399 .noext,
1358014400 .inreg,
1358114401 .@"noalias",
1358214402 .nocapture,
......@@ -13594,11 +14414,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1359414414 .readnone,
1359514415 .readonly,
1359614416 .writeonly,
14417 .writable,
14418 .dead_on_unwind,
1359714419 .alwaysinline,
1359814420 .builtin,
1359914421 .cold,
1360014422 .convergent,
13601 .disable_sanitizer_information,
14423 .disable_sanitizer_instrumentation,
1360214424 .fn_ret_thunk_extern,
1360314425 .hot,
1360414426 .inlinehint,
......@@ -13607,6 +14429,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1360714429 .naked,
1360814430 .nobuiltin,
1360914431 .nocallback,
14432 .nodivergencesource,
1361014433 .noduplicate,
1361114434 .noimplicitfloat,
1361214435 .@"noinline",
......@@ -13623,6 +14446,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1362314446 .nosanitize_bounds,
1362414447 .nosanitize_coverage,
1362514448 .null_pointer_is_valid,
14449 .optdebug,
1362614450 .optforfuzzing,
1362714451 .optnone,
1362814452 .optsize,
......@@ -13633,18 +14457,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1363314457 .sanitize_thread,
1363414458 .sanitize_hwaddress,
1363514459 .sanitize_memtag,
14460 .sanitize_realtime,
14461 .sanitize_realtime_blocking,
14462 .sanitize_alloc_token,
1363614463 .speculative_load_hardening,
1363714464 .speculatable,
1363814465 .ssp,
1363914466 .sspstrong,
1364014467 .sspreq,
1364114468 .strictfp,
14469 .denormal_fpenv,
1364214470 .nocf_check,
1364314471 .shadowcallstack,
1364414472 .mustprogress,
13645 .no_sanitize_address,
13646 .no_sanitize_hwaddress,
13647 .sanitize_address_dyninit,
14473 .nooutline,
14474 .nocreateundeforpoison,
1364814475 => {
1364914476 try record.ensureUnusedCapacity(self.gpa, 2);
1365014477 record.appendAssumeCapacity(0);
......@@ -13670,6 +14497,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1367014497 record.appendAssumeCapacity(@backingInt(kind));
1367114498 record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0);
1367214499 },
14500 .captures => |captures| {
14501 try record.ensureUnusedCapacity(self.gpa, 3);
14502 record.appendAssumeCapacity(1);
14503 record.appendAssumeCapacity(@backingInt(kind));
14504 record.appendAssumeCapacity(@as(u32, @bitCast(captures)));
14505 },
1367314506 .dereferenceable,
1367414507 .dereferenceable_or_null,
1367514508 => |size| {
......@@ -13684,6 +14517,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1368414517 record.appendAssumeCapacity(@backingInt(kind));
1368514518 record.appendAssumeCapacity(@as(u32, @bitCast(fpclass)));
1368614519 },
14520 .initializes => @panic("TODO"),
14521 .dead_on_return => @panic("TODO"),
14522 .range => @panic("TODO"),
1368714523 .allockind => |allockind| {
1368814524 try record.ensureUnusedCapacity(self.gpa, 3);
1368914525 record.appendAssumeCapacity(1);
......@@ -14099,7 +14935,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1409914935 }
1410014936 },
1410114937 .string => {
14102 const str: String = @fromBackingInt(@intCast(data));
14938 const str: String = @fromBackingInt(data);
1410314939 if (str == .none) {
1410414940 try constants_block.writeAbbrev(ConstantsBlock.Null{});
1410514941 } else {
......@@ -14226,7 +15062,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1422615062 .dso_local_equivalent,
1422715063 .no_cfi,
1422815064 => |tag| {
14229 const function: Function.Index = @fromBackingInt(@intCast(data));
15065 const function: Function.Index = @fromBackingInt(data);
1423015066 try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{
1423115067 .code = switch (tag) {
1423215068 .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT,
......@@ -14609,7 +15445,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1460915445 }, metadata_adapter);
1461015446 },
1461115447 .constant => {
14612 const constant: Constant = @fromBackingInt(@intCast(data));
15448 const constant: Constant = @fromBackingInt(data);
1461315449 try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{
1461415450 .ty = constant.typeOf(self),
1461515451 .constant = constant,
......@@ -14778,7 +15614,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1477815614 var adapter: FunctionAdapter = .{
1477915615 .metadata_adapter = metadata_adapter,
1478015616 .func = &func,
14781 .instruction_index = @fromBackingInt(@intCast(0)),
15617 .instruction_index = @fromBackingInt(0),
1478215618 };
1478315619
1478415620 // Emit function level metadata block
......@@ -14789,7 +15625,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1478915625 for (func.debug_values) |value| {
1479015626 try metadata_block.writeAbbrev(MetadataBlock.Value{
1479115627 .ty = value.typeOf(@fromBackingInt(@intCast(func_index)), self),
14792 .value = @fromBackingInt(@intCast(adapter.getValueIndex(value.toValue()))),
15628 .value = @fromBackingInt(adapter.getValueIndex(value.toValue())),
1479315629 });
1479415630 }
1479515631
......@@ -15071,10 +15907,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1507115907 });
1507215908 },
1507315909 .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{
15074 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),
15910 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
1507515911 }),
1507615912 .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{
15077 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),
15913 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
1507815914 .fast_math = FastMath.fast,
1507915915 }),
1508015916 .extractvalue => {
......@@ -15274,7 +16110,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
1527416110 try function_block.writeUnabbrev(16, record.items);
1527516111 },
1527616112 .ret => try function_block.writeAbbrev(FunctionBlock.Ret{
15277 .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))),
16113 .val = adapter.getOffsetValueIndex(@fromBackingInt(data)),
1527816114 }),
1527916115 .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}),
1528016116 .atomicrmw => {
lib/std/zig/target.zig+23-25
......@@ -499,34 +499,32 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 {
499499}
500500
501501pub fn intAlignment(target: *const std.Target, bits: u16) u16 {
502 return switch (target.cpu.arch) {
503 .x86 => switch (bits) {
504 0...8 => 1,
505 9...16 => 2,
506 17...32 => 4,
507 33...64 => switch (target.os.tag) {
508 .uefi, .windows => 8,
509 else => 4,
510 },
511 else => 16,
512 },
513 .x86_64 => switch (bits) {
514 0...8 => 1,
515 9...16 => 2,
516 17...32 => 4,
517 33...64 => 8,
518 else => 16,
519 },
520 else => switch (bits) {
521 0 => 1,
522 else => @min(
523 std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)),
524 target.cMaxIntAlignment(),
525 ),
526 },
502 return switch (bits) {
503 0 => 1,
504 else => @min(
505 std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)),
506 target.cMaxIntAlignment(),
507 ),
527508 };
528509}
529510
511pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.Float {
512 if (target.cpu.has(.x86, .soft_float)) return .soft;
513 // Marks targets where clang does not even provide a usable C type.
514 const no_c_type_available = .soft;
515 switch (bits) {
516 else => unreachable,
517 16 => if (target.cpu.arch.isMIPS() or target.cpu.arch.isPowerPC()) return no_c_type_available,
518 32, 64 => {},
519 80 => if (target.cTypeBitSize(.longdouble) != 80) return no_c_type_available,
520 128 => {
521 if (target.cpu.arch.isX86()) return .hard; // if (target.abi == .msvc) __m128i else __float128
522 if (target.cTypeBitSize(.longdouble) != 128) return no_c_type_available;
523 },
524 }
525 return .hard;
526}
527
530528const std = @import("std");
531529const assert = std.debug.assert;
532530const Allocator = std.mem.Allocator;
lib/std/zon/parse.zig+1-6
......@@ -9,7 +9,6 @@
99//! For lower level control over parsing, see `std.zig.Zoir`.
1010
1111const std = @import("std");
12const builtin = @import("builtin");
1312const Allocator = std.mem.Allocator;
1413const Ast = std.zig.Ast;
1514const Zoir = std.zig.Zoir;
......@@ -1868,8 +1867,6 @@ test "std.zon tuples" {
18681867
18691868// Test sizes 0 to 3 since small sizes get parsed differently
18701869test "std.zon arrays and slices" {
1871 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881
1872
18731870 const gpa = std.testing.allocator;
18741871
18751872 // Literals
......@@ -2802,8 +2799,6 @@ test "std.zon negative char" {
28022799}
28032800
28042801test "std.zon parse float" {
2805 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
2806
28072802 const gpa = std.testing.allocator;
28082803
28092804 // Test decimals
......@@ -3135,7 +3130,7 @@ test "std.zon free on error" {
31353130}
31363131
31373132test "std.zon vector" {
3138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330
3133 const builtin = @import("builtin");
31393134 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957
31403135
31413136 const gpa = std.testing.allocator;
lib/std/zon/stringify.zig-3
......@@ -1151,9 +1151,6 @@ test "std.zon depth limits" {
11511151}
11521152
11531153test "std.zon stringify primitives" {
1154 // Issue: https://github.com/ziglang/zig/issues/20880
1155 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
1156
11571154 try expectSerializeEqual(
11581155 \\.{
11591156 \\ .a = 1.5,
lib/zig.h+3079-991
......@@ -166,6 +166,12 @@
166166#endif
167167#define zig_expand_has_builtin(b) zig_has_builtin(b)
168168
169#if defined(__has_feature)
170#define zig_has_feature(feature) __has_feature(feature)
171#else
172#define zig_has_feature(feature) 0
173#endif
174
169175#if defined(__has_attribute)
170176#define zig_has_attribute(attribute) __has_attribute(attribute)
171177#else
......@@ -175,9 +181,9 @@
175181#if __STDC_VERSION__ >= 201112L
176182#define zig_static_assert(cond, msg) _Static_assert(cond, msg)
177183#elif zig_has_attribute(unused)
178#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused))
184#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused))
179185#else
180#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)]
186#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1]
181187#endif
182188
183189#if __STDC_VERSION__ >= 202311L
......@@ -193,10 +199,8 @@
193199#endif
194200
195201#if defined(zig_msvc)
196#define zig_const_arr
197202#define zig_callconv(c) __##c
198203#else
199#define zig_const_arr static const
200204#define zig_callconv(c) __attribute__((c))
201205#endif
202206
......@@ -267,12 +271,20 @@
267271
268272#if __STDC_VERSION__ >= 202311L
269273#define zig_align(alignment) alignas(alignment)
270#elif __STDC_VERSION__ >= 201112L
274#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas)
271275#define zig_align(alignment) _Alignas(alignment)
272276#else
273277#define zig_align(alignment) zig_under_align(alignment)
274278#endif
275279
280#if __STDC_VERSION__ >= 202311L
281#define zig_alignOf(Type) alignof(Type)
282#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof)
283#define zig_alignOf(Type) _Alignof(Type)
284#else
285#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type))
286#endif
287
276288#if zig_has_attribute(aligned) || defined(zig_tinyc)
277289#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
278290#elif defined(zig_msvc)
......@@ -350,11 +362,9 @@
350362#define zig_export(symbol, name) __attribute__((alias(symbol)))
351363#else
352364#define zig_export(symbol, name) ; \
353 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
365 __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol))
354366#endif
355367
356#define zig_mangled_tentative zig_mangled
357#define zig_mangled_final zig_mangled
358368#if defined(zig_msvc)
359369#define zig_mangled(mangled, unmangled) ; \
360370 zig_export(#mangled, unmangled)
......@@ -364,7 +374,7 @@
364374#else /* zig_msvc */
365375#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
366376#define zig_mangled_export(mangled, unmangled, symbol) \
367 zig_mangled_final(mangled, unmangled) \
377 zig_mangled(mangled, unmangled) \
368378 zig_export(symbol, unmangled)
369379#endif /* zig_msvc */
370380
......@@ -550,6 +560,9 @@
550560#define zig_noreturn
551561#endif
552562
563#define zig_has_always 1
564#define zig_has_never 0
565
553566#define zig_compiler_rt_abbrev_uint32_t si
554567#define zig_compiler_rt_abbrev_int32_t si
555568#define zig_compiler_rt_abbrev_uint64_t di
......@@ -560,7 +573,11 @@
560573#define zig_compiler_rt_abbrev_zig_f32 sf
561574#define zig_compiler_rt_abbrev_zig_f64 df
562575#define zig_compiler_rt_abbrev_zig_f80 xf
576#ifdef zig_powerpc
577#define zig_compiler_rt_abbrev_zig_f128 kf
578#else
563579#define zig_compiler_rt_abbrev_zig_f128 tf
580#endif
564581
565582zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
566583zig_extern void *memset (void *, int, size_t);
......@@ -645,16 +662,6 @@ typedef signed long long int16_t;
645662#define INT16_MAX ( INT16_C(0x7FFF))
646663#define UINT16_MAX ( INT16_C(0xFFFF))
647664
648#if defined(zig_ez80)
649typedef unsigned int uint24_t;
650typedef signed int int24_t;
651#define INT24_C(c) c
652#define UINT24_C(c) c##U
653#endif
654#define INT24_MIN (~INT24_C(0x7FFF))
655#define INT24_MAX ( INT24_C(0x7FFF))
656#define UINT24_MAX ( INT24_C(0xFFFF))
657
658665#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
659666typedef unsigned char uint32_t;
660667typedef signed char int32_t;
......@@ -685,17 +692,6 @@ typedef signed long long int32_t;
685692#define INT32_MAX ( INT32_C(0x7FFFFFFF))
686693#define UINT32_MAX ( INT32_C(0xFFFFFFFF))
687694
688#if defined(zig_ez80)
689typedef unsigned __int48 uint48_t;
690typedef signed __int48 int48_t;
691#define INT48_C(c) c
692/* no suffix */
693#define UINT48_C(c) ((uint48_t)(c))
694#endif
695#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
696#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
697#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
698
699695#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
700696typedef unsigned char uint64_t;
701697typedef signed char int64_t;
......@@ -726,6 +722,27 @@ typedef signed long long int64_t;
726722#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
727723#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))
728724
725#if defined(zig_ez80)
726
727typedef unsigned int uint24_t;
728typedef signed int int24_t;
729#define INT24_C(c) c
730#define UINT24_C(c) c##U
731#define INT24_MIN (~INT24_C(0x7FFF))
732#define INT24_MAX ( INT24_C(0x7FFF))
733#define UINT24_MAX ( INT24_C(0xFFFF))
734
735typedef unsigned __int48 uint48_t;
736typedef signed __int48 int48_t;
737#define INT48_C(c) c
738/* no suffix */
739#define UINT48_C(c) ((uint48_t)(c))
740#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
741#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
742#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
743
744#endif
745
729746typedef size_t uintptr_t;
730747typedef ptrdiff_t intptr_t;
731748
......@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;
739756#define zig_maxInt_i16 INT16_MAX
740757#define zig_minInt_u16 UINT16_C(0)
741758#define zig_maxInt_u16 UINT16_MAX
742#define zig_minInt_i24 INT24_MIN
743#define zig_maxInt_i24 INT24_MAX
744#define zig_minInt_u24 UINT24_C(0)
745#define zig_maxInt_u24 UINT24_MAX
746759#define zig_minInt_i32 INT32_MIN
747760#define zig_maxInt_i32 INT32_MAX
748761#define zig_minInt_u32 UINT32_C(0)
749762#define zig_maxInt_u32 UINT32_MAX
750#define zig_minInt_i48 INT48_MIN
751#define zig_maxInt_i48 INT48_MAX
752#define zig_minInt_u48 UINT48_C(0)
753#define zig_maxInt_u48 UINT48_MAX
754763#define zig_minInt_i64 INT64_MIN
755764#define zig_maxInt_i64 INT64_MAX
756765#define zig_minInt_u64 UINT64_C(0)
757766#define zig_maxInt_u64 UINT64_MAX
758767
768// zig_promoted_T implements C integral promotions except with signedness preserved, which
769// allows wrapping operations to avoid the ub that would be caused by the normal promotion.
770
771#if INT8_MAX <= INT_MAX
772typedef unsigned int zig_promoted_i8;
773#elif INT8_MAX <= LONG_MAX
774typedef unsigned long zig_promoted_i8;
775#elif INT8_MAX <= LLONG_MAX
776typedef unsigned long long zig_promoted_i8;
777#else
778typedef int8_t zig_promoted_i8;
779#endif
780#if UINT8_MAX <= UINT_MAX
781typedef unsigned int zig_promoted_u8;
782#elif UINT8_MAX <= ULONG_MAX
783typedef unsigned long zig_promoted_u8;
784#elif UINT8_MAX <= ULLONG_MAX
785typedef unsigned long long zig_promoted_u8;
786#else
787typedef uint8_t zig_promoted_u8;
788#endif
789
790#if INT16_MAX <= INT_MAX
791typedef unsigned int zig_promoted_i16;
792#elif INT16_MAX <= LONG_MAX
793typedef unsigned long zig_promoted_i16;
794#elif INT16_MAX <= LLONG_MAX
795typedef unsigned long long zig_promoted_i16;
796#else
797typedef int16_t zig_promoted_i16;
798#endif
799#if UINT16_MAX <= UINT_MAX
800typedef unsigned int zig_promoted_u16;
801#elif UINT16_MAX <= ULONG_MAX
802typedef unsigned long zig_promoted_u16;
803#elif UINT16_MAX <= ULLONG_MAX
804typedef unsigned long long zig_promoted_u16;
805#else
806typedef uint16_t zig_promoted_u16;
807#endif
808
809#if INT32_MAX <= INT_MAX
810typedef unsigned int zig_promoted_i32;
811#elif INT32_MAX <= LONG_MAX
812typedef unsigned long zig_promoted_i32;
813#elif INT32_MAX <= LLONG_MAX
814typedef unsigned long long zig_promoted_i32;
815#else
816typedef int32_t zig_promoted_i32;
817#endif
818#if UINT32_MAX <= UINT_MAX
819typedef unsigned int zig_promoted_u32;
820#elif UINT32_MAX <= ULONG_MAX
821typedef unsigned long zig_promoted_u32;
822#elif UINT32_MAX <= ULLONG_MAX
823typedef unsigned long long zig_promoted_u32;
824#else
825typedef uint32_t zig_promoted_u32;
826#endif
827
828#if INT64_MAX <= INT_MAX
829typedef unsigned int zig_promoted_i64;
830#elif INT64_MAX <= LONG_MAX
831typedef unsigned long zig_promoted_i64;
832#elif INT64_MAX <= LLONG_MAX
833typedef unsigned long long zig_promoted_i64;
834#else
835typedef int64_t zig_promoted_i64;
836#endif
837#if UINT64_MAX <= UINT_MAX
838typedef unsigned int zig_promoted_u64;
839#elif UINT64_MAX <= ULONG_MAX
840typedef unsigned long zig_promoted_u64;
841#elif UINT64_MAX <= ULLONG_MAX
842typedef unsigned long long zig_promoted_u64;
843#else
844typedef uint64_t zig_promoted_u64;
845#endif
846
847#ifdef zig_ez80
848
849#define zig_minInt_i24 INT24_MIN
850#define zig_maxInt_i24 INT24_MAX
851#define zig_minInt_u24 UINT24_C(0)
852#define zig_maxInt_u24 UINT24_MAX
853#define zig_minInt_i48 INT48_MIN
854#define zig_maxInt_i48 INT48_MAX
855#define zig_minInt_u48 UINT48_C(0)
856#define zig_maxInt_u48 UINT48_MAX
857
858#if INT24_MAX <= INT_MAX
859typedef unsigned int zig_promoted_i24;
860#elif INT24_MAX <= LONG_MAX
861typedef unsigned long zig_promoted_i24;
862#elif INT24_MAX <= LLONG_MAX
863typedef unsigned long long zig_promoted_i24;
864#else
865typedef int24_t zig_promoted_i24;
866#endif
867#if UINT24_MAX <= UINT_MAX
868typedef unsigned int zig_promoted_u24;
869#elif UINT24_MAX <= ULONG_MAX
870typedef unsigned long zig_promoted_u24;
871#elif UINT24_MAX <= ULLONG_MAX
872typedef unsigned long long zig_promoted_u24;
873#else
874typedef uint24_t zig_promoted_u24;
875#endif
876
877#if INT48_MAX <= INT_MAX
878typedef unsigned int zig_promoted_i48;
879#elif INT48_MAX <= LONG_MAX
880typedef unsigned long zig_promoted_i48;
881#elif INT48_MAX <= LLONG_MAX
882typedef unsigned long long zig_promoted_i48;
883#else
884typedef int48_t zig_promoted_i48;
885#endif
886#if UINT48_MAX <= UINT_MAX
887typedef unsigned int zig_promoted_u48;
888#elif UINT48_MAX <= ULONG_MAX
889typedef unsigned long zig_promoted_u48;
890#elif UINT48_MAX <= ULLONG_MAX
891typedef unsigned long long zig_promoted_u48;
892#else
893typedef uint48_t zig_promoted_u48;
894#endif
895
896#endif
897
759898#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
760899#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
761900#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
......@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;
770909 zig_operator(Type, Type, operation, operator)
771910#define zig_shift_operator(Type, operation, operator) \
772911 zig_operator(Type, uint8_t, operation, operator)
773#define zig_int_helpers(w, PromotedUnsigned) \
912
913#define zig_int_casts_common(bw, sw) \
914 static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \
915 return arg; \
916 } \
917\
918 static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \
919 return (uint##bw##_t)arg; \
920 } \
921\
922 static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \
923 return arg; \
924 } \
925\
926 static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \
927 return arg; \
928 } \
929\
930 static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \
931 return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \
932 } \
933\
934 static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \
935 return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \
936 ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \
937 }
938#define zig_int_operators(w) \
774939 zig_basic_operator(uint##w##_t, and_u##w, &) \
775940 zig_basic_operator( int##w##_t, and_i##w, &) \
776941 zig_basic_operator(uint##w##_t, or_u##w, |) \
......@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;
786951 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
787952 } \
788953\
789 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
790 return val ^ zig_maxInt_u(w, bits); \
954 static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \
955 return arg ^ zig_maxInt_u(w, bits); \
791956 } \
792957\
793 static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \
958 static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \
794959 (void)bits; \
795 return ~val; \
960 return ~arg; \
796961 } \
797962\
798 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
799 return val & zig_maxInt_u(w, bits); \
963 zig_basic_operator(uint##w##_t, divFloor_u##w, /) \
964\
965 static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \
966 return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \
800967 } \
801968\
802 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
803 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
804 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
969 static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
970 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
805971 } \
806972\
807 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \
808 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \
973 static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \
974 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
975 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
809976 } \
810977\
811 zig_basic_operator(uint##w##_t, div_floor_u##w, /) \
978 zig_basic_operator(uint##w##_t, mod_u##w, %) \
979 zig_int_casts_common(w, w) \
812980\
813 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
814 return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \
981 static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
982 return zig_u##w##_truncate_u##w(arg, bits); \
815983 } \
816984\
817 static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
818 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
985 static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
986 return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \
819987 } \
820988\
821 static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \
822 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
823 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
989 static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
990 return zig_i##w##_truncate_i##w(arg, bits); \
824991 } \
825992\
826 zig_basic_operator(uint##w##_t, mod_u##w, %) \
993 static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
994 return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \
995 } \
827996\
828997 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
829998 int##w##_t rem = lhs % rhs; \
......@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;
8311000 } \
8321001\
8331002 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
834 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
1003 return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \
8351004 } \
8361005\
8371006 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
838 return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \
1007 return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \
8391008 } \
8401009\
8411010 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
842 return zig_wrap_u##w(lhs + rhs, bits); \
1011 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \
8431012 } \
8441013\
8451014 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
846 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
1015 return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \
8471016 } \
8481017\
8491018 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
850 return zig_wrap_u##w(lhs - rhs, bits); \
1019 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \
8511020 } \
8521021\
8531022 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
854 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
1023 return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \
8551024 } \
8561025\
8571026 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
858 return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \
1027 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \
8591028 } \
8601029\
8611030 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
862 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
1031 return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \
1032 } \
1033\
1034 static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \
1035 int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \
1036 return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \
1037 } \
1038\
1039 static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1040 return lhs < rhs ? lhs : rhs; \
1041 } \
1042\
1043 static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \
1044 return lhs < rhs ? lhs : rhs; \
1045 } \
1046\
1047 static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1048 return lhs >= rhs ? lhs : rhs; \
1049 } \
1050\
1051 static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \
1052 return lhs >= rhs ? lhs : rhs; \
8631053 }
864#if UINT8_MAX <= UINT_MAX
865zig_int_helpers(8, unsigned int)
866#elif UINT8_MAX <= ULONG_MAX
867zig_int_helpers(8, unsigned long)
868#elif UINT8_MAX <= ULLONG_MAX
869zig_int_helpers(8, unsigned long long)
870#else
871zig_int_helpers(8, uint8_t)
872#endif
873#if UINT16_MAX <= UINT_MAX
874zig_int_helpers(16, unsigned int)
875#elif UINT16_MAX <= ULONG_MAX
876zig_int_helpers(16, unsigned long)
877#elif UINT16_MAX <= ULLONG_MAX
878zig_int_helpers(16, unsigned long long)
879#else
880zig_int_helpers(16, uint16_t)
881#endif
882#if defined(zig_ez80)
883#if UINT24_MAX <= UINT_MAX
884zig_int_helpers(24, unsigned int)
885#elif UINT24_MAX <= ULONG_MAX
886zig_int_helpers(24, unsigned long)
887#elif UINT24_MAX <= ULLONG_MAX
888zig_int_helpers(24, unsigned long long)
889#else
890zig_int_helpers(24, uint24_t)
891#endif
892#endif
893#if UINT32_MAX <= UINT_MAX
894zig_int_helpers(32, unsigned int)
895#elif UINT32_MAX <= ULONG_MAX
896zig_int_helpers(32, unsigned long)
897#elif UINT32_MAX <= ULLONG_MAX
898zig_int_helpers(32, unsigned long long)
899#else
900zig_int_helpers(32, uint32_t)
901#endif
902#if defined(zig_ez80)
903#if UINT24_MAX <= UINT_MAX
904zig_int_helpers(48, unsigned int)
905#elif UINT24_MAX <= ULONG_MAX
906zig_int_helpers(48, unsigned long)
907#elif UINT24_MAX <= ULLONG_MAX
908zig_int_helpers(48, unsigned long long)
909#else
910zig_int_helpers(48, uint48_t)
911#endif
912#endif
913#if UINT64_MAX <= UINT_MAX
914zig_int_helpers(64, unsigned int)
915#elif UINT64_MAX <= ULONG_MAX
916zig_int_helpers(64, unsigned long)
917#elif UINT64_MAX <= ULLONG_MAX
918zig_int_helpers(64, unsigned long long)
919#else
920zig_int_helpers(64, uint64_t)
1054zig_int_operators(8)
1055zig_int_operators(16)
1056zig_int_operators(32)
1057zig_int_operators(64)
1058#ifdef zig_ez80
1059zig_int_operators(24)
1060zig_int_operators(48)
1061#endif
1062
1063#define zig_int_casts(bw, sw) \
1064 static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \
1065 return (uint##sw##_t)arg; \
1066 } \
1067\
1068 static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \
1069 return (uint##sw##_t)arg; \
1070 } \
1071\
1072 static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \
1073 return (int##sw##_t)arg; \
1074 } \
1075\
1076 static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \
1077 return (int##sw##_t)arg; \
1078 } \
1079\
1080 zig_int_casts_common(bw, sw)
1081zig_int_casts(16, 8)
1082zig_int_casts(32, 8)
1083zig_int_casts(64, 8)
1084zig_int_casts(32, 16)
1085zig_int_casts(64, 16)
1086zig_int_casts(64, 32)
1087#ifdef zig_ez80
1088zig_int_casts(32, 24)
1089zig_int_casts(48, 24)
1090zig_int_casts(64, 24)
1091zig_int_casts(64, 48)
9211092#endif
9221093
9231094static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
9241095#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9251096 uint32_t full_res;
9261097 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
927 *res = zig_wrap_u32(full_res, bits);
1098 *res = zig_u32_truncate_u32(full_res, bits);
9281099 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
9291100#else
9301101 *res = zig_addw_u32(lhs, rhs, bits);
......@@ -936,19 +1107,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
9361107#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9371108 int32_t full_res;
9381109 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1110 *res = zig_i32_truncate_i32(full_res, bits);
1111 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9391112#else
940 int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs);
941 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1113 *res = zig_addw_i32(lhs, rhs, bits);
1114 return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0);
9421115#endif
943 *res = zig_wrap_i32(full_res, bits);
944 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9451116}
9461117
9471118static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
9481119#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9491120 uint64_t full_res;
9501121 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
951 *res = zig_wrap_u64(full_res, bits);
1122 *res = zig_u64_truncate_u64(full_res, bits);
9521123 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
9531124#else
9541125 *res = zig_addw_u64(lhs, rhs, bits);
......@@ -960,24 +1131,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
9601131#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9611132 int64_t full_res;
9621133 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1134 *res = zig_i64_truncate_i64(full_res, bits);
1135 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9631136#else
964 int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs);
965 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1137 *res = zig_addw_i64(lhs, rhs, bits);
1138 return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0);
9661139#endif
967 *res = zig_wrap_i64(full_res, bits);
968 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9691140}
9701141
9711142static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
9721143#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9731144 uint8_t full_res;
9741145 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
975 *res = zig_wrap_u8(full_res, bits);
1146 *res = zig_u8_truncate_u8(full_res, bits);
9761147 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
9771148#else
9781149 uint32_t full_res;
9791150 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
980 *res = (uint8_t)full_res;
1151 *res = zig_u8_intCast_u32(full_res);
9811152 return overflow;
9821153#endif
9831154}
......@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
9861157#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9871158 int8_t full_res;
9881159 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
989 *res = zig_wrap_i8(full_res, bits);
1160 *res = zig_i8_truncate_i8(full_res, bits);
9901161 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
9911162#else
9921163 int32_t full_res;
9931164 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
994 *res = (int8_t)full_res;
1165 *res = zig_i8_intCast_i32(full_res);
9951166 return overflow;
9961167#endif
9971168}
......@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
10001171#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10011172 uint16_t full_res;
10021173 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1003 *res = zig_wrap_u16(full_res, bits);
1174 *res = zig_u16_truncate_u16(full_res, bits);
10041175 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
10051176#else
10061177 uint32_t full_res;
10071178 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1008 *res = (uint16_t)full_res;
1179 *res = zig_u16_intCast_u32(full_res);
10091180 return overflow;
10101181#endif
10111182}
......@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
10141185#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10151186 int16_t full_res;
10161187 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1017 *res = zig_wrap_i16(full_res, bits);
1188 *res = zig_i16_truncate_i16(full_res, bits);
10181189 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
10191190#else
10201191 int32_t full_res;
10211192 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1022 *res = (int16_t)full_res;
1193 *res = zig_i16_intCast_i32(full_res);
10231194 return overflow;
10241195#endif
10251196}
10261197
10271198#if defined(zig_ez80)
1199
10281200static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
10291201#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10301202 uint24_t full_res;
10311203 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1032 *res = zig_wrap_u24(full_res, bits);
1204 *res = zig_u24_truncate_u24(full_res, bits);
10331205 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
10341206#else
10351207 uint32_t full_res;
10361208 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1037 *res = (uint24_t)full_res;
1209 *res = zig_u24_intCast_u32(full_res);
10381210 return overflow;
10391211#endif
10401212}
......@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
10431215#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10441216 int24_t full_res;
10451217 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1046 *res = zig_wrap_i24(full_res, bits);
1218 *res = zig_i24_truncate_i24(full_res, bits);
10471219 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
10481220#else
10491221 int32_t full_res;
10501222 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1051 *res = (int24_t)full_res;
1223 *res = zig_i24_intCast_i32(full_res);
10521224 return overflow;
10531225#endif
10541226}
1055#endif
10561227
1057#if defined(zig_ez80)
10581228static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
10591229#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10601230 uint48_t full_res;
10611231 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1062 *res = zig_wrap_u48(full_res, bits);
1232 *res = zig_u48_truncate_u48(full_res, bits);
10631233 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
10641234#else
10651235 uint64_t full_res;
10661236 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);
1067 *res = (uint48_t)full_res;
1237 *res = zig_u48_intCast_u64(full_res);
10681238 return overflow;
10691239#endif
10701240}
......@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
10731243#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10741244 int48_t full_res;
10751245 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1076 *res = zig_wrap_i48(full_res, bits);
1246 *res = zig_i48_truncate_i48(full_res, bits);
10771247 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
10781248#else
10791249 int64_t full_res;
10801250 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);
1081 *res = (int48_t)full_res;
1251 *res = zig_i48_intCast_i64(full_res);
10821252 return overflow;
10831253#endif
10841254}
1255
10851256#endif
10861257
10871258static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
10881259#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
10891260 uint32_t full_res;
10901261 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1091 *res = zig_wrap_u32(full_res, bits);
1262 *res = zig_u32_truncate_u32(full_res, bits);
10921263 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
10931264#else
10941265 *res = zig_subw_u32(lhs, rhs, bits);
......@@ -1100,20 +1271,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
11001271#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11011272 int32_t full_res;
11021273 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1274 *res = zig_i32_truncate_i32(full_res, bits);
1275 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11031276#else
1104 int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs);
1105 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1277 *res = zig_subw_i32(lhs, rhs, bits);
1278 return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0);
11061279#endif
1107 *res = zig_wrap_i32(full_res, bits);
1108 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11091280}
11101281
1111
11121282static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
11131283#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11141284 uint64_t full_res;
11151285 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1116 *res = zig_wrap_u64(full_res, bits);
1286 *res = zig_u64_truncate_u64(full_res, bits);
11171287 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
11181288#else
11191289 *res = zig_subw_u64(lhs, rhs, bits);
......@@ -1125,24 +1295,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
11251295#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11261296 int64_t full_res;
11271297 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1298 *res = zig_i64_truncate_i64(full_res, bits);
1299 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11281300#else
1129 int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs);
1130 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1301 *res = zig_subw_i64(lhs, rhs, bits);
1302 return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0);
11311303#endif
1132 *res = zig_wrap_i64(full_res, bits);
1133 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11341304}
11351305
11361306static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
11371307#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11381308 uint8_t full_res;
11391309 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1140 *res = zig_wrap_u8(full_res, bits);
1310 *res = zig_u8_truncate_u8(full_res, bits);
11411311 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
11421312#else
11431313 uint32_t full_res;
11441314 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1145 *res = (uint8_t)full_res;
1315 *res = zig_u8_intCast_u32(full_res);
11461316 return overflow;
11471317#endif
11481318}
......@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
11511321#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11521322 int8_t full_res;
11531323 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1154 *res = zig_wrap_i8(full_res, bits);
1324 *res = zig_i8_truncate_i8(full_res, bits);
11551325 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
11561326#else
11571327 int32_t full_res;
11581328 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1159 *res = (int8_t)full_res;
1329 *res = zig_i8_intCast_i32(full_res);
11601330 return overflow;
11611331#endif
11621332}
......@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
11651335#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11661336 uint16_t full_res;
11671337 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1168 *res = zig_wrap_u16(full_res, bits);
1338 *res = zig_u16_truncate_u16(full_res, bits);
11691339 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
11701340#else
11711341 uint32_t full_res;
11721342 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1173 *res = (uint16_t)full_res;
1343 *res = zig_u16_intCast_u32(full_res);
11741344 return overflow;
11751345#endif
11761346}
......@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
11791349#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11801350 int16_t full_res;
11811351 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1182 *res = zig_wrap_i16(full_res, bits);
1352 *res = zig_i16_truncate_i16(full_res, bits);
11831353 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
11841354#else
11851355 int32_t full_res;
11861356 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1187 *res = (int16_t)full_res;
1357 *res = zig_i16_intCast_i32(full_res);
11881358 return overflow;
11891359#endif
11901360}
11911361
11921362#if defined(zig_ez80)
1363
11931364static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
11941365#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11951366 uint24_t full_res;
11961367 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1197 *res = zig_wrap_u24(full_res, bits);
1368 *res = zig_u24_truncate_u24(full_res, bits);
11981369 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
11991370#else
12001371 uint32_t full_res;
12011372 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1202 *res = (uint24_t)full_res;
1373 *res = zig_u24_intCast_u32(full_res);
12031374 return overflow;
12041375#endif
12051376}
......@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
12081379#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12091380 int24_t full_res;
12101381 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1211 *res = zig_wrap_i24(full_res, bits);
1382 *res = zig_i24_truncate_i24(full_res, bits);
12121383 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
12131384#else
12141385 int32_t full_res;
12151386 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1216 *res = (int24_t)full_res;
1387 *res = zig_i24_intCast_i32(full_res);
12171388 return overflow;
12181389#endif
12191390}
1220#endif
12211391
1222#if defined(zig_ez80)
12231392static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
12241393#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12251394 uint48_t full_res;
12261395 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1227 *res = zig_wrap_u48(full_res, bits);
1396 *res = zig_u48_truncate_u48(full_res, bits);
12281397 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
12291398#else
12301399 uint64_t full_res;
12311400 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);
1232 *res = (uint48_t)full_res;
1401 *res = zig_u48_intCast_u64(full_res);
12331402 return overflow;
12341403#endif
12351404}
......@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
12381407#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12391408 int48_t full_res;
12401409 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1241 *res = zig_wrap_i48(full_res, bits);
1410 *res = zig_i48_truncate_i48(full_res, bits);
12421411 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
12431412#else
12441413 int64_t full_res;
12451414 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);
1246 *res = (int48_t)full_res;
1415 *res = zig_i48_intCast_i64(full_res);
12471416 return overflow;
12481417#endif
12491418}
1419
12501420#endif
12511421
12521422static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
12531423#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12541424 uint32_t full_res;
12551425 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1256 *res = zig_wrap_u32(full_res, bits);
1426 *res = zig_u32_truncate_u32(full_res, bits);
12571427 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
12581428#else
12591429 *res = zig_mulw_u32(lhs, rhs, bits);
......@@ -1261,8 +1431,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
12611431#endif
12621432}
12631433
1264zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12651434static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
1435 zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12661436#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12671437 int32_t full_res;
12681438 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
......@@ -1271,7 +1441,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
12711441 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
12721442 bool overflow = overflow_int != 0;
12731443#endif
1274 *res = zig_wrap_i32(full_res, bits);
1444 *res = zig_i32_truncate_i32(full_res, bits);
12751445 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
12761446}
12771447
......@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
12791449#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12801450 uint64_t full_res;
12811451 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1282 *res = zig_wrap_u64(full_res, bits);
1452 *res = zig_u64_truncate_u64(full_res, bits);
12831453 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
12841454#else
12851455 *res = zig_mulw_u64(lhs, rhs, bits);
......@@ -1287,8 +1457,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
12871457#endif
12881458}
12891459
1290zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12911460static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
1461 zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12921462#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12931463 int64_t full_res;
12941464 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
......@@ -1297,7 +1467,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
12971467 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
12981468 bool overflow = overflow_int != 0;
12991469#endif
1300 *res = zig_wrap_i64(full_res, bits);
1470 *res = zig_i64_truncate_i64(full_res, bits);
13011471 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
13021472}
13031473
......@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
13051475#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13061476 uint8_t full_res;
13071477 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1308 *res = zig_wrap_u8(full_res, bits);
1478 *res = zig_u8_truncate_u8(full_res, bits);
13091479 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
13101480#else
13111481 uint32_t full_res;
13121482 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1313 *res = (uint8_t)full_res;
1483 *res = zig_u8_intCast_u32(full_res);
13141484 return overflow;
13151485#endif
13161486}
......@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
13191489#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13201490 int8_t full_res;
13211491 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1322 *res = zig_wrap_i8(full_res, bits);
1492 *res = zig_i8_truncate_i8(full_res, bits);
13231493 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
13241494#else
13251495 int32_t full_res;
13261496 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1327 *res = (int8_t)full_res;
1497 *res = zig_i8_intCast_i32(full_res);
13281498 return overflow;
13291499#endif
13301500}
......@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
13331503#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13341504 uint16_t full_res;
13351505 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1336 *res = zig_wrap_u16(full_res, bits);
1506 *res = zig_u16_truncate_u16(full_res, bits);
13371507 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
13381508#else
13391509 uint32_t full_res;
13401510 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1341 *res = (uint16_t)full_res;
1511 *res = zig_u16_intCast_u32(full_res);
13421512 return overflow;
13431513#endif
13441514}
......@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
13471517#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13481518 int16_t full_res;
13491519 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1350 *res = zig_wrap_i16(full_res, bits);
1520 *res = zig_i16_truncate_i16(full_res, bits);
13511521 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
13521522#else
13531523 int32_t full_res;
13541524 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1355 *res = (int16_t)full_res;
1525 *res = zig_i16_intCast_i32(full_res);
13561526 return overflow;
13571527#endif
13581528}
13591529
13601530#if defined(zig_ez80)
1531
13611532static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
13621533#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13631534 uint24_t full_res;
13641535 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1365 *res = zig_wrap_u24(full_res, bits);
1536 *res = zig_u24_truncate_u24(full_res, bits);
13661537 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
13671538#else
13681539 uint32_t full_res;
13691540 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1370 *res = (uint24_t)full_res;
1541 *res = zig_u24_intCast_u32(full_res);
13711542 return overflow;
13721543#endif
13731544}
......@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
13761547#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13771548 int24_t full_res;
13781549 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1379 *res = zig_wrap_i24(full_res, bits);
1550 *res = zig_i24_truncate_i24(full_res, bits);
13801551 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
13811552#else
13821553 int32_t full_res;
13831554 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1384 *res = (int24_t)full_res;
1555 *res = zig_i24_intCast_i32(full_res);
13851556 return overflow;
13861557#endif
13871558}
1388#endif
13891559
1390#if defined(zig_ez80)
13911560static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
13921561#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13931562 uint48_t full_res;
13941563 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1395 *res = zig_wrap_u48(full_res, bits);
1564 *res = zig_u48_truncate_u48(full_res, bits);
13961565 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
13971566#else
13981567 uint64_t full_res;
13991568 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);
1400 *res = (uint48_t)full_res;
1569 *res = zig_u48_intCast_u64(full_res);
14011570 return overflow;
14021571#endif
14031572}
......@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14061575#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
14071576 int48_t full_res;
14081577 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1409 *res = zig_wrap_i48(full_res, bits);
1578 *res = zig_i48_truncate_i48(full_res, bits);
14101579 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
14111580#else
14121581 int64_t full_res;
14131582 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);
1414 *res = (int48_t)full_res;
1583 *res = zig_i48_intCast_i64(full_res);
14151584 return overflow;
14161585#endif
14171586}
1587
14181588#endif
14191589
1420#define zig_int_builtins(w) \
1590#define zig_shls_builtins(lw, rw) \
1591 static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1592 uint##lw##_t res; \
1593 if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1594 return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \
1595 } \
1596\
1597 static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1598 int##lw##_t res; \
1599 if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1600 return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \
1601 lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \
1602 }
1603#define zig_int_sat_builtins(w) \
14211604 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
14221605 *res = zig_shlw_u##w(lhs, rhs, bits); \
14231606 return lhs > zig_maxInt_u(w, bits) >> rhs; \
......@@ -1429,18 +1612,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14291612 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
14301613 } \
14311614\
1432 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1433 uint##w##_t res; \
1434 if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \
1435 return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \
1436 } \
1437\
1438 static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1439 int##w##_t res; \
1440 if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
1441 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
1442 lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
1443 } \
1615 zig_shls_builtins(w, 8) \
1616 zig_shls_builtins(w, 16) \
1617 zig_shls_builtins(w, 32) \
1618 zig_shls_builtins(w, 64) \
14441619\
14451620 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
14461621 uint##w##_t res; \
......@@ -1474,332 +1649,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14741649 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
14751650 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
14761651 }
1477zig_int_builtins(8)
1478zig_int_builtins(16)
1479#if defined(zig_ez80)
1480zig_int_builtins(24)
1481#endif
1482zig_int_builtins(32)
1652zig_int_sat_builtins(8)
1653zig_int_sat_builtins(16)
1654zig_int_sat_builtins(32)
1655zig_int_sat_builtins(64)
14831656#if defined(zig_ez80)
1484zig_int_builtins(48)
1657zig_int_sat_builtins(24)
1658zig_int_sat_builtins(48)
14851659#endif
1486zig_int_builtins(64)
14871660
1488#define zig_builtin8(name, val) __builtin_##name(val)
1661#define zig_builtin8(name, arg) __builtin_##name(arg)
14891662typedef unsigned int zig_Builtin8;
14901663
1491#define zig_builtin16(name, val) __builtin_##name(val)
1664#define zig_builtin16(name, arg) __builtin_##name(arg)
14921665typedef unsigned int zig_Builtin16;
14931666
1494#if defined(zig_ez80)
1495#define zig_builtin24(name, val) __builtin_##name(val)
1496typedef unsigned int zig_Builtin24;
1497#endif
1498
14991667#if INT_MIN <= INT32_MIN
1500#define zig_builtin32(name, val) __builtin_##name(val)
1668#define zig_builtin32(name, arg) __builtin_##name(arg)
15011669typedef unsigned int zig_Builtin32;
15021670#elif LONG_MIN <= INT32_MIN
1503#define zig_builtin32(name, val) __builtin_##name##l(val)
1671#define zig_builtin32(name, arg) __builtin_##name##l(arg)
15041672typedef unsigned long zig_Builtin32;
15051673#endif
15061674
1507#if defined(zig_ez80)
1508#define zig_builtin48(name, val) __builtin_##name(val)
1509typedef unsigned long long zig_Builtin48;
1510#endif
1511
15121675#if INT_MIN <= INT64_MIN
1513#define zig_builtin64(name, val) __builtin_##name(val)
1676#define zig_builtin64(name, arg) __builtin_##name(arg)
15141677typedef unsigned int zig_Builtin64;
15151678#elif LONG_MIN <= INT64_MIN
1516#define zig_builtin64(name, val) __builtin_##name##l(val)
1679#define zig_builtin64(name, arg) __builtin_##name##l(arg)
15171680typedef unsigned long zig_Builtin64;
15181681#elif LLONG_MIN <= INT64_MIN
1519#define zig_builtin64(name, val) __builtin_##name##ll(val)
1682#define zig_builtin64(name, arg) __builtin_##name##ll(arg)
15201683typedef unsigned long long zig_Builtin64;
15211684#endif
15221685
1523static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
1524 return zig_wrap_u8(val >> (8 - bits), bits);
1686#if defined(zig_ez80)
1687#define zig_builtin24(name, arg) __builtin_##name(arg)
1688typedef unsigned int zig_Builtin24;
1689#define zig_builtin48(name, arg) __builtin_##name(arg)
1690typedef unsigned long long zig_Builtin48;
1691#endif
1692
1693static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) {
1694 return zig_u8_truncate_u8(arg >> (8 - bits), bits);
15251695}
15261696
1527static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
1528 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
1697static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) {
1698 return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits);
15291699}
15301700
1531static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
1701static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) {
15321702 uint16_t full_res;
15331703#if zig_has_builtin(bswap16) || defined(zig_gcc)
1534 full_res = __builtin_bswap16(val);
1704 full_res = __builtin_bswap16(arg);
15351705#else
1536 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
1537 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
1706 full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 |
1707 (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0;
15381708#endif
1539 return zig_wrap_u16(full_res >> (16 - bits), bits);
1709 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
15401710}
15411711
1542static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
1543 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
1712static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) {
1713 return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits);
15441714}
15451715
15461716#if defined(zig_ez80)
1547static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) {
1717static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) {
15481718 uint24_t full_res;
15491719#if zig_has_builtin(bswap24) || defined(zig_gcc)
1550 full_res = __builtin_bswap24(val);
1720 full_res = __builtin_bswap24(arg);
15511721#else
1552 full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 |
1553 (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0;
1722 full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 |
1723 (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0;
15541724#endif
1555 return zig_wrap_u24(full_res >> (24 - bits), bits);
1725 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
15561726}
15571727
1558static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) {
1559 return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits);
1728static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) {
1729 return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits);
15601730}
15611731#endif
15621732
1563static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
1733static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) {
15641734 uint32_t full_res;
15651735#if zig_has_builtin(bswap32) || defined(zig_gcc)
1566 full_res = __builtin_bswap32(val);
1736 full_res = __builtin_bswap32(arg);
15671737#else
1568 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
1569 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
1738 full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 |
1739 (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0;
15701740#endif
1571 return zig_wrap_u32(full_res >> (32 - bits), bits);
1741 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
15721742}
15731743
1574static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
1575 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
1744static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) {
1745 return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits);
15761746}
15771747
15781748#if defined(zig_ez80)
1579static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) {
1749static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) {
15801750 uint48_t full_res;
15811751#if zig_has_builtin(bswap48) || defined(zig_gcc)
1582 full_res = __builtin_bswap48(val);
1752 full_res = __builtin_bswap48(arg);
15831753#else
1584 full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 |
1585 (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0;
1754 full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 |
1755 (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0;
15861756#endif
1587 return zig_wrap_u48(full_res >> (48 - bits), bits);
1757 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
15881758}
15891759
1590static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) {
1591 return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits);
1760static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) {
1761 return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits);
15921762}
15931763#endif
15941764
1595static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
1765static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) {
15961766 uint64_t full_res;
15971767#if zig_has_builtin(bswap64) || defined(zig_gcc)
1598 full_res = __builtin_bswap64(val);
1768 full_res = __builtin_bswap64(arg);
15991769#else
1600 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
1601 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
1770 full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 |
1771 (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0;
16021772#endif
1603 return zig_wrap_u64(full_res >> (64 - bits), bits);
1773 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
16041774}
16051775
1606static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
1607 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
1776static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) {
1777 return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits);
16081778}
16091779
1610static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
1780static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) {
16111781 uint8_t full_res;
16121782#if zig_has_builtin(bitreverse8)
1613 full_res = __builtin_bitreverse8(val);
1783 full_res = __builtin_bitreverse8(arg);
16141784#else
16151785 static uint8_t const lut[0x10] = {
16161786 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
16171787 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
16181788 };
1619 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
1789 full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0;
16201790#endif
1621 return zig_wrap_u8(full_res >> (8 - bits), bits);
1791 return zig_u8_truncate_u8(full_res >> (8 - bits), bits);
16221792}
16231793
1624static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
1625 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
1794static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) {
1795 return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits);
16261796}
16271797
1628static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
1798static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) {
16291799 uint16_t full_res;
16301800#if zig_has_builtin(bitreverse16)
1631 full_res = __builtin_bitreverse16(val);
1801 full_res = __builtin_bitreverse16(arg);
16321802#else
1633 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
1634 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
1803 full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 |
1804 (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0;
16351805#endif
1636 return zig_wrap_u16(full_res >> (16 - bits), bits);
1806 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
16371807}
16381808
1639static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
1640 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
1809static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) {
1810 return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits);
16411811}
16421812
16431813#if defined(zig_ez80)
1644static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) {
1814static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) {
16451815 uint24_t full_res;
16461816#if zig_has_builtin(bitreverse24)
1647 full_res = __builtin_bitreverse24(val);
1817 full_res = __builtin_bitreverse24(arg);
16481818#else
1649 full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 |
1650 (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0;
1819 full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 |
1820 (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0;
16511821#endif
1652 return zig_wrap_u24(full_res >> (24 - bits), bits);
1822 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
16531823}
16541824
1655static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) {
1656 return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits);
1825static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) {
1826 return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits);
16571827}
16581828#endif
16591829
1660static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
1830static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) {
16611831 uint32_t full_res;
16621832#if zig_has_builtin(bitreverse32)
1663 full_res = __builtin_bitreverse32(val);
1833 full_res = __builtin_bitreverse32(arg);
16641834#else
1665 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
1666 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
1835 full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 |
1836 (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0;
16671837#endif
1668 return zig_wrap_u32(full_res >> (32 - bits), bits);
1838 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
16691839}
16701840
1671static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
1672 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
1841static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) {
1842 return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits);
16731843}
16741844
16751845#if defined(zig_ez80)
1676static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) {
1846static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) {
16771847 uint48_t full_res;
16781848#if zig_has_builtin(bitreverse48)
1679 full_res = __builtin_bitreverse48(val);
1849 full_res = __builtin_bitreverse48(arg);
16801850#else
1681 full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 |
1682 (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0;
1851 full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 |
1852 (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0;
16831853#endif
1684 return zig_wrap_u32(full_res >> (48 - bits), bits);
1854 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
16851855}
16861856
1687static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) {
1688 return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits);
1857static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) {
1858 return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits);
16891859}
16901860#endif
16911861
1692static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
1862static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) {
16931863 uint64_t full_res;
16941864#if zig_has_builtin(bitreverse64)
1695 full_res = __builtin_bitreverse64(val);
1865 full_res = __builtin_bitreverse64(arg);
16961866#else
1697 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
1698 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
1867 full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 |
1868 (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0;
16991869#endif
1700 return zig_wrap_u64(full_res >> (64 - bits), bits);
1870 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
17011871}
17021872
1703static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
1704 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
1873static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) {
1874 return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits);
17051875}
17061876
1707#define zig_builtin_popcount_common(w) \
1708 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
1709 return zig_popcount_u##w((uint##w##_t)val, bits); \
1877#define zig_builtin_popCount_common(w) \
1878 static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \
1879 return zig_popCount_u##w((uint##w##_t)arg, bits); \
17101880 }
1711#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc)
1712#define zig_builtin_popcount(w) \
1713 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1881#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc)
1882#define zig_builtin_popCount(w) \
1883 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17141884 (void)bits; \
1715 return zig_builtin##w(popcount, val); \
1885 return zig_builtin##w(popcount, arg); \
17161886 } \
17171887\
1718 zig_builtin_popcount_common(w)
1888 zig_builtin_popCount_common(w)
17191889#else
1720#define zig_builtin_popcount(w) \
1721 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1890#define zig_builtin_popCount(w) \
1891 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17221892 (void)bits; \
1723 uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
1893 uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \
17241894 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
17251895 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
17261896 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
17271897 } \
17281898\
1729 zig_builtin_popcount_common(w)
1730#endif
1731zig_builtin_popcount(8)
1732zig_builtin_popcount(16)
1733#if defined(zig_ez80)
1734zig_builtin_popcount(24)
1899 zig_builtin_popCount_common(w)
17351900#endif
1736zig_builtin_popcount(32)
1901zig_builtin_popCount(8)
1902zig_builtin_popCount(16)
1903zig_builtin_popCount(32)
1904zig_builtin_popCount(64)
17371905#if defined(zig_ez80)
1738zig_builtin_popcount(48)
1906zig_builtin_popCount(24)
1907zig_builtin_popCount(48)
17391908#endif
1740zig_builtin_popcount(64)
17411909
17421910#define zig_builtin_ctz_common(w) \
1743 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
1744 return zig_ctz_u##w((uint##w##_t)val, bits); \
1911 static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \
1912 return zig_ctz_u##w((uint##w##_t)arg, bits); \
17451913 }
17461914#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)
17471915#define zig_builtin_ctz(w) \
1748 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1749 if (val == 0) return bits; \
1750 return zig_builtin##w(ctz, val); \
1916 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1917 if (arg == 0) return bits; \
1918 return zig_builtin##w(ctz, arg); \
17511919 } \
17521920\
17531921 zig_builtin_ctz_common(w)
17541922#else
17551923#define zig_builtin_ctz(w) \
1756 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1757 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
1924 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1925 return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \
17581926 } \
17591927\
17601928 zig_builtin_ctz_common(w)
17611929#endif
17621930zig_builtin_ctz(8)
17631931zig_builtin_ctz(16)
1764#if defined(zig_ez80)
1765zig_builtin_ctz(24)
1766#endif
17671932zig_builtin_ctz(32)
1933zig_builtin_ctz(64)
17681934#if defined(zig_ez80)
1935zig_builtin_ctz(24)
17691936zig_builtin_ctz(48)
17701937#endif
1771zig_builtin_ctz(64)
17721938
17731939#define zig_builtin_clz_common(w) \
1774 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
1775 return zig_clz_u##w((uint##w##_t)val, bits); \
1940 static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \
1941 return zig_clz_u##w((uint##w##_t)arg, bits); \
17761942 }
17771943#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)
17781944#define zig_builtin_clz(w) \
1779 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1780 if (val == 0) return bits; \
1781 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1945 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1946 if (arg == 0) return bits; \
1947 return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
17821948 } \
17831949\
17841950 zig_builtin_clz_common(w)
17851951#else
17861952#define zig_builtin_clz(w) \
1787 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1788 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
1953 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1954 return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \
17891955 } \
17901956\
17911957 zig_builtin_clz_common(w)
17921958#endif
17931959zig_builtin_clz(8)
17941960zig_builtin_clz(16)
1795#if defined(zig_ez80)
1796zig_builtin_clz(24)
1797#endif
17981961zig_builtin_clz(32)
1962zig_builtin_clz(64)
17991963#if defined(zig_ez80)
1964zig_builtin_clz(24)
18001965zig_builtin_clz(48)
18011966#endif
1802zig_builtin_clz(64)
18031967
18041968/* ======================== 128-bit Integer Support ========================= */
18051969
......@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)
18161980typedef unsigned __int128 zig_u128;
18171981typedef signed __int128 zig_i128;
18181982
1819#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1820#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1821#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1822#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1823#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1824#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1825#define zig_hi_i128(val) (( int64_t)((val) >> 64))
1826#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
1827#define zig_bitCast_u128(val) ((zig_u128)(val))
1828#define zig_bitCast_i128(val) ((zig_i128)(val))
1983#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1984#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1985#define zig_make_u128(hi, lo) zig_init_u128(hi, lo)
1986#define zig_make_i128(hi, lo) zig_init_i128(hi, lo)
1987#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64))
1988#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0))
1989#define zig_hi_i128(arg) (( int64_t)((arg) >> 64))
1990#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0))
18291991#define zig_cmp_int128(Type) \
18301992 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18311993 return (lhs > rhs) - (lhs < rhs); \
......@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;
18351997 return lhs operator rhs; \
18361998 }
18371999
1838#else /* zig_has_int128 */
2000static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2001 return lhs << rhs;
2002}
18392003
1840#if zig_little_endian
1841typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1842typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
2004static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2005 return lhs >> rhs;
2006}
2007
2008static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2009 return lhs << rhs;
2010}
2011
2012static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2013 // This works around a GCC miscompilation, but it has the side benefit of
2014 // emitting better code. It is behind the `#if` because it depends on
2015 // arithmetic right shift, which is implementation-defined in C, but should
2016 // be guaranteed on any GCC-compatible compiler.
2017#if defined(zig_gnuc)
2018 return lhs >> rhs;
18432019#else
1844typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1845typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
2020 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
2021 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
18462022#endif
2023}
18472024
1848#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1849#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
2025#else /* zig_has_int128 */
18502026
1851#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */
1852#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1853#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1854#else /* But non-MSVC doesn't like the unprotected commas */
1855#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1856#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1857#endif
1858#define zig_hi_u128(val) ((val).hi)
1859#define zig_lo_u128(val) ((val).lo)
1860#define zig_hi_i128(val) ((val).hi)
1861#define zig_lo_i128(val) ((val).lo)
1862#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
1863#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
2027#if zig_little_endian
2028typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128;
2029typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128;
2030#else
2031typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128;
2032typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128;
2033#endif
2034
2035#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo }
2036#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo }
2037#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo)
2038#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo)
2039#define zig_hi_u128(arg) (arg).hi
2040#define zig_lo_u128(arg) (arg).lo
2041#define zig_hi_i128(arg) (arg).hi
2042#define zig_lo_i128(arg) (arg).lo
18642043#define zig_cmp_int128(Type) \
18652044 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18662045 return (lhs.hi == rhs.hi) \
......@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
18722051 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
18732052 }
18742053
2054static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2055 if (rhs == UINT8_C(0)) return lhs;
2056 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2057 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2058}
2059
2060static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2061 if (rhs == UINT8_C(0)) return lhs;
2062 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
2063 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
2064}
2065
2066static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2067 if (rhs == UINT8_C(0)) return lhs;
2068 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2069 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2070}
2071
2072static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2073 if (rhs == UINT8_C(0)) return lhs;
2074 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) };
2075 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2076}
2077
18752078#endif /* zig_has_int128 */
18762079
18772080#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
......@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)
18912094zig_bit_int128(u128, xor, ^)
18922095zig_bit_int128(i128, xor, ^)
18932096
1894static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs);
2097static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) {
2098 return (uint8_t)zig_lo_u128(arg);
2099}
2100static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) {
2101 return (uint8_t)zig_lo_i128(arg);
2102}
2103static inline int8_t zig_i8_intCast_i128(zig_i128 arg) {
2104 return (int8_t)zig_lo_i128(arg);
2105}
2106static inline int8_t zig_i8_intCast_u128(zig_u128 arg) {
2107 return (int8_t)zig_lo_u128(arg);
2108}
18952109
1896#if zig_has_int128
2110static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) {
2111 return (uint16_t)zig_lo_u128(arg);
2112}
2113static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) {
2114 return (uint16_t)zig_lo_i128(arg);
2115}
2116static inline int16_t zig_i16_intCast_i128(zig_i128 arg) {
2117 return (int16_t)zig_lo_i128(arg);
2118}
2119static inline int16_t zig_i16_intCast_u128(zig_u128 arg) {
2120 return (int16_t)zig_lo_u128(arg);
2121}
18972122
1898static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1899 return val ^ zig_maxInt_u(128, bits);
2123static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) {
2124 return (uint32_t)zig_lo_u128(arg);
2125}
2126static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) {
2127 return (uint32_t)zig_lo_i128(arg);
2128}
2129static inline int32_t zig_i32_intCast_i128(zig_i128 arg) {
2130 return (int32_t)zig_lo_i128(arg);
2131}
2132static inline int32_t zig_i32_intCast_u128(zig_u128 arg) {
2133 return (int32_t)zig_lo_u128(arg);
19002134}
19012135
1902static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1903 (void)bits;
1904 return ~val;
2136static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) {
2137 return zig_lo_u128(arg);
2138}
2139static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) {
2140 return zig_lo_i128(arg);
2141}
2142static inline int64_t zig_i64_intCast_i128(zig_i128 arg) {
2143 return (int64_t)zig_lo_i128(arg);
2144}
2145static inline int64_t zig_i64_intCast_u128(zig_u128 arg) {
2146 return (int64_t)zig_lo_u128(arg);
19052147}
19062148
1907static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1908 return lhs >> rhs;
2149static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) {
2150 return zig_make_u128(UINT8_C(0), arg);
2151}
2152static inline zig_u128 zig_u128_intCast_i8(int8_t arg) {
2153 return zig_make_u128(UINT8_C(0), (uint8_t)arg);
2154}
2155static inline zig_i128 zig_i128_intCast_i8(int8_t arg) {
2156 return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg);
2157}
2158static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) {
2159 return zig_make_i128(INT8_C(0), arg);
19092160}
19102161
1911static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1912 return lhs << rhs;
2162static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) {
2163 return zig_make_u128(UINT16_C(0), arg);
2164}
2165static inline zig_u128 zig_u128_intCast_i16(int16_t arg) {
2166 return zig_make_u128(UINT16_C(0), (uint16_t)arg);
2167}
2168static inline zig_i128 zig_i128_intCast_i16(int16_t arg) {
2169 return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg);
2170}
2171static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) {
2172 return zig_make_i128(INT16_C(0), arg);
19132173}
19142174
1915static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1916 // This works around a GCC miscompilation, but it has the side benefit of
1917 // emitting better code. It is behind the `#if` because it depends on
1918 // arithmetic right shift, which is implementation-defined in C, but should
1919 // be guaranteed on any GCC-compatible compiler.
1920#if defined(zig_gnuc)
1921 return lhs >> rhs;
2175static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) {
2176 return zig_make_u128(UINT32_C(0), arg);
2177}
2178static inline zig_u128 zig_u128_intCast_i32(int32_t arg) {
2179 return zig_make_u128(UINT32_C(0), (uint32_t)arg);
2180}
2181static inline zig_i128 zig_i128_intCast_i32(int32_t arg) {
2182 return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg);
2183}
2184static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) {
2185 return zig_make_i128(INT32_C(0), arg);
2186}
2187
2188static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) {
2189 return zig_make_u128(UINT64_C(0), arg);
2190}
2191static inline zig_u128 zig_u128_intCast_i64(int64_t arg) {
2192 return zig_make_u128(UINT64_C(0), (uint64_t)arg);
2193}
2194static inline zig_i128 zig_i128_intCast_i64(int64_t arg) {
2195 return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg);
2196}
2197static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) {
2198 return zig_make_i128(INT64_C(0), arg);
2199}
2200
2201static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) {
2202 return arg;
2203}
2204static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) {
2205#if zig_has_int128
2206 return (zig_u128)arg;
19222207#else
1923 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1924 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
2208 return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
2209#endif
2210}
2211static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) {
2212 return arg;
2213}
2214static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) {
2215#if zig_has_int128
2216 return (zig_i128)arg;
2217#else
2218 return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
19252219#endif
19262220}
19272221
1928static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
1929 return lhs << rhs;
2222#define zig_int128_cast_builtins(w) \
2223 static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \
2224 return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \
2225 } \
2226\
2227 static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \
2228 return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \
2229 }
2230zig_int128_cast_builtins(8)
2231zig_int128_cast_builtins(16)
2232zig_int128_cast_builtins(32)
2233zig_int128_cast_builtins(64)
2234
2235static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) {
2236 return zig_and_u128(arg, zig_maxInt_u(128, bits));
2237}
2238static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) {
2239 if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg));
2240 int64_t lo = zig_i64_truncate_i128(arg, bits);
2241 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2242}
2243
2244static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2245 (void)bits;
2246 return arg;
2247}
2248static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2249 return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits);
2250}
2251static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2252 (void)bits;
2253 return arg;
2254}
2255static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2256 return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits);
2257}
2258
2259#if zig_has_int128
2260
2261static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2262 return arg ^ zig_maxInt_u(128, bits);
2263}
2264
2265static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2266 (void)bits;
2267 return ~arg;
19302268}
19312269
19322270static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
......@@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
19532291 return lhs * rhs;
19542292}
19552293
1956static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2294static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
19572295 return lhs / rhs;
19582296}
19592297
1960static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2298static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
19612299 return lhs / rhs;
19622300}
19632301
......@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
19712309
19722310#else /* zig_has_int128 */
19732311
1974static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1975 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1976}
1977
1978static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1979 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1980}
1981
1982static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1983 if (rhs == UINT8_C(0)) return lhs;
1984 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
1985 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
1986}
1987
1988static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1989 if (rhs == UINT8_C(0)) return lhs;
1990 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1991 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
1992}
1993
1994static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1995 if (rhs == UINT8_C(0)) return lhs;
1996 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) };
1997 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2312static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2313 if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) };
2314 return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) };
19982315}
19992316
2000static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2001 if (rhs == UINT8_C(0)) return lhs;
2002 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2003 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2317static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2318 (void)bits;
2319 return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo };
20042320}
20052321
20062322static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
......@@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
20272343 return res;
20282344}
20292345
2030zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20312346static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
2347 zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20322348 return __multi3(lhs, rhs);
20332349}
20342350
20352351static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
2036 return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs)));
2352 return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128));
20372353}
20382354
2039zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
2040static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2355static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
2356 zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
20412357 return __udivti3(lhs, rhs);
20422358}
20432359
2044zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
2045static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2360static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
2361 zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
20462362 return __divti3(lhs, rhs);
20472363}
20482364
2049zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20502365static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
2366 zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20512367 return __umodti3(lhs, rhs);
20522368}
20532369
2054zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20552370static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
2371 zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20562372 return __modti3(lhs, rhs);
20572373}
20582374
20592375#endif /* zig_has_int128 */
20602376
2061#define zig_div_floor_u128 zig_div_trunc_u128
2377#define zig_divFloor_u128 zig_divTrunc_u128
20622378
2063static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
2379static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) {
20642380 zig_i128 rem = zig_rem_i128(lhs, rhs);
20652381 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20662382 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);
2067 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
2383 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
20682384}
20692385
2070static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) {
2386static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) {
20712387 zig_u128 rem = zig_rem_u128(lhs, rhs);
20722388 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)
20732389 ? UINT64_C(1) : UINT64_C(0);
2074 return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
2390 return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
20752391}
20762392
2077static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) {
2393static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) {
20782394 zig_i128 rem = zig_rem_i128(lhs, rhs);
20792395 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20802396 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)
20812397 : INT64_C(0);
2082 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
2398 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
20832399}
20842400
20852401#define zig_mod_u128 zig_rem_u128
......@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
21072423 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
21082424}
21092425
2110static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
2111 return zig_and_u128(val, zig_maxInt_u(128, bits));
2112}
2113
2114static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
2115 if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
2116 int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits);
2117 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2118}
2119
21202426static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
2121 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
2427 return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits);
21222428}
21232429
21242430static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {
2125 return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits);
2431 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits);
21262432}
21272433
21282434static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2129 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
2435 return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits);
21302436}
21312437
21322438static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2133 return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2439 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits);
21342440}
21352441
21362442static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2137 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
2443 return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits);
21382444}
21392445
21402446static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2141 return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2447 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits);
21422448}
21432449
21442450static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2145 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
2451 return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits);
21462452}
21472453
21482454static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2149 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2455 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits);
21502456}
21512457
2152static inline zig_u128 zig_abs_i128(zig_i128 val) {
2153 zig_i128 tmp = zig_shr_i128(val, 127);
2154 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));
2458static inline zig_u128 zig_abs_i128(zig_i128 arg) {
2459 zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128));
2460 return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp);
21552461}
21562462
21572463#if zig_has_int128
......@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21602466#if zig_has_builtin(add_overflow)
21612467 zig_u128 full_res;
21622468 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
2163 *res = zig_wrap_u128(full_res, bits);
2469 *res = zig_u128_truncate_u128(full_res, bits);
21642470 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21652471#else
21662472 *res = zig_addw_u128(lhs, rhs, bits);
......@@ -2176,7 +2482,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
21762482 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);
21772483 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
21782484#endif
2179 *res = zig_wrap_i128(full_res, bits);
2485 *res = zig_i128_truncate_i128(full_res, bits);
21802486 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
21812487}
21822488
......@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21842490#if zig_has_builtin(sub_overflow)
21852491 zig_u128 full_res;
21862492 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
2187 *res = zig_wrap_u128(full_res, bits);
2493 *res = zig_u128_truncate_u128(full_res, bits);
21882494 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21892495#else
21902496 *res = zig_subw_u128(lhs, rhs, bits);
......@@ -2200,7 +2506,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
22002506 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);
22012507 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
22022508#endif
2203 *res = zig_wrap_i128(full_res, bits);
2509 *res = zig_i128_truncate_i128(full_res, bits);
22042510 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22052511}
22062512
......@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
22082514#if zig_has_builtin(mul_overflow)
22092515 zig_u128 full_res;
22102516 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
2211 *res = zig_wrap_u128(full_res, bits);
2517 *res = zig_u128_truncate_u128(full_res, bits);
22122518 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
22132519#else
22142520 *res = zig_mulw_u128(lhs, rhs, bits);
......@@ -2216,8 +2522,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
22162522#endif
22172523}
22182524
2219zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22202525static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2526 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22212527#if zig_has_builtin(mul_overflow)
22222528 zig_i128 full_res;
22232529 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
......@@ -2226,50 +2532,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
22262532 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22272533 bool overflow = overflow_int != 0;
22282534#endif
2229 *res = zig_wrap_i128(full_res, bits);
2535 *res = zig_i128_truncate_i128(full_res, bits);
22302536 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22312537}
22322538
22332539#else /* zig_has_int128 */
22342540
22352541static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2236 uint64_t hi;
2237 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2238 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2542 if (bits <= UINT8_C(64)) {
2543 uint64_t lo;
2544 bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2545 *res = zig_u128_intCast_u64(lo);
2546 return overflow;
2547 } else {
2548 uint64_t hi;
2549 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2550 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2551 }
22392552}
22402553
22412554static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2242 int64_t hi;
2243 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2244 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2555 if (bits <= UINT8_C(64)) {
2556 int64_t lo;
2557 bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2558 *res = zig_i128_intCast_i64(lo);
2559 return overflow;
2560 } else {
2561 int64_t hi;
2562 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2563 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2564 }
22452565}
22462566
22472567static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2248 uint64_t hi;
2249 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2250 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2568 if (bits <= UINT8_C(64)) {
2569 uint64_t lo;
2570 bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2571 *res = zig_u128_intCast_u64(lo);
2572 return overflow;
2573 } else {
2574 uint64_t hi;
2575 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2576 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2577 }
22512578}
22522579
22532580static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2254 int64_t hi;
2255 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2256 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2581 if (bits <= UINT8_C(64)) {
2582 int64_t lo;
2583 bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2584 *res = zig_i128_intCast_i64(lo);
2585 return overflow;
2586 } else {
2587 int64_t hi;
2588 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2589 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2590 }
22572591}
22582592
22592593static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22602594 *res = zig_mulw_u128(lhs, rhs, bits);
2261 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
2262 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
2595 return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) &&
2596 zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
22632597}
22642598
2265zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22662599static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2600 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22672601 int overflow_int;
22682602 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22692603 bool overflow = overflow_int != 0 ||
22702604 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
22712605 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);
2272 *res = zig_wrap_i128(full_res, bits);
2606 *res = zig_i128_truncate_i128(full_res, bits);
22732607 return overflow;
22742608}
22752609
......@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8
22822616
22832617static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
22842618 *res = zig_shlw_i128(lhs, rhs, bits);
2285 zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
2619 zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits);
22862620 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
22872621 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
22882622}
22892623
2290static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2624#define zig_int128_shls_builtins(rw) \
2625 static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2626 zig_u128 res; \
2627 if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2628 switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \
2629 case 0: return zig_minInt_u(128, bits); \
2630 case 1: return zig_maxInt_u(128, bits); \
2631 default: zig_unreachable(); \
2632 } \
2633 } \
2634\
2635 static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2636 zig_i128 res; \
2637 if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2638 switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \
2639 case -1: return zig_minInt_i(128, bits); \
2640 case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \
2641 case 1: return zig_maxInt_i(128, bits); \
2642 default: zig_unreachable(); \
2643 } \
2644 }
2645zig_int128_shls_builtins(8)
2646zig_int128_shls_builtins(16)
2647zig_int128_shls_builtins(32)
2648zig_int128_shls_builtins(64)
2649
2650static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22912651 zig_u128 res;
22922652 if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res;
22932653 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {
2294 case 0: return zig_make_u128(0, 0);
2295 case 1: return zig_maxInt_u(128, bits);
2654 case INT32_C(0): return zig_make_u128(0, 0);
2655 case INT32_C(1): return zig_maxInt_u(128, bits);
22962656 default: zig_unreachable();
22972657 }
22982658}
22992659
2300static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
2660static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
23012661 zig_i128 res;
23022662 if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res;
23032663 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {
2304 case -1: return zig_minInt_i(128, bits);
2305 case 0: return zig_make_i128(0, 0);
2306 case 1: return zig_maxInt_i(128, bits);
2664 case -INT32_C(1): return zig_minInt_i(128, bits);
2665 case INT32_C(0): return zig_make_i128(0, 0);
2666 case INT32_C(1): return zig_maxInt_i(128, bits);
23072667 default: zig_unreachable();
23082668 }
23092669}
......@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
23412701 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
23422702}
23432703
2344static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
2345 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);
2346 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
2347 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
2704static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) {
2705 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits);
2706 if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64));
2707 return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64));
23482708}
23492709
2350static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {
2351 return zig_clz_u128(zig_bitCast_u128(val), bits);
2710static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) {
2711 return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23522712}
23532713
2354static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
2355 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
2356 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
2714static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) {
2715 if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64));
2716 return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64);
23572717}
23582718
2359static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {
2360 return zig_ctz_u128(zig_bitCast_u128(val), bits);
2719static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) {
2720 return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23612721}
23622722
2363static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
2364 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
2365 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
2723static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) {
2724 return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) +
2725 zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64));
23662726}
23672727
2368static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {
2369 return zig_popcount_u128(zig_bitCast_u128(val), bits);
2728static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) {
2729 return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits);
23702730}
23712731
2372static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) {
2732static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) {
23732733 zig_u128 full_res;
23742734#if zig_has_builtin(bswap128)
2375 full_res = __builtin_bswap128(val);
2735 full_res = __builtin_bswap128(arg);
23762736#else
2377 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
2378 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
2737 full_res = zig_make_u128(
2738 zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)),
2739 zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64))
2740 );
23792741#endif
23802742 return zig_shr_u128(full_res, UINT8_C(128) - bits);
23812743}
23822744
2383static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {
2384 return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));
2745static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) {
2746 return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23852747}
23862748
2387static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
2388 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
2389 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
2390 UINT8_C(128) - bits);
2749static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) {
2750 return zig_shr_u128(zig_make_u128(
2751 zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)),
2752 zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64))
2753 ), UINT8_C(128) - bits);
23912754}
23922755
2393static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
2394 return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));
2756static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) {
2757 return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23952758}
23962759
23972760#if zig_has_int128
......@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
24112774/* ========================== Big Integer Support =========================== */
24122775
24132776static inline uint16_t zig_int_bytes(uint16_t bits) {
2414 uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT;
2777 uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1);
24152778 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
2779
24162780 while (alignment / 2 >= bytes) alignment /= 2;
24172781 return (bytes + alignment - 1) / alignment * alignment;
24182782}
24192783
2420static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2784static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) {
2785 uint8_t *res_bytes = res;
2786 uint16_t size = zig_int_bytes(bits);
2787 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2788 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2789 uint8_t sign_byte;
2790 uint8_t fill_byte;
2791
2792 if (is_signed) {
2793 int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits);
2794
2795 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2796 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2797 } else {
2798 sign_byte = zig_minInt_u(8, remainder_bits);
2799 fill_byte = UINT8_C(0);
2800 }
2801
2802#if zig_little_endian
2803 memset(&res_bytes[0], zig_minInt_u8, byte_offset);
2804 res_bytes[byte_offset] = sign_byte;
2805 byte_offset += UINT16_C(1);
2806 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2807#else
2808 byte_offset = size - UINT16_C(1) - byte_offset;
2809 memset(&res_bytes[0], fill_byte, byte_offset);
2810 res_bytes[byte_offset] = sign_byte;
2811 byte_offset += UINT16_C(1);
2812 memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset);
2813#endif
2814}
2815
2816static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) {
2817 uint8_t *res_bytes = res;
2818 uint16_t size = zig_int_bytes(bits);
2819 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2820 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2821 uint8_t sign_byte;
2822 uint8_t fill_byte;
2823
2824 if (is_signed) {
2825 int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits);
2826
2827 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2828 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2829 } else {
2830 sign_byte = zig_maxInt_u(8, remainder_bits);
2831 fill_byte = UINT8_C(0);
2832 }
2833
2834#if zig_little_endian
2835 memset(&res_bytes[0], zig_maxInt_u8, byte_offset);
2836 res_bytes[byte_offset] = sign_byte;
2837 byte_offset += UINT16_C(1);
2838 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2839#else
2840 byte_offset = size - UINT16_C(1) - byte_offset;
2841 memset(&res_bytes[0], fill_byte, byte_offset);
2842 res_bytes[byte_offset] = sign_byte;
2843 byte_offset += UINT16_C(1);
2844 memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset);
2845#endif
2846}
2847
2848static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) {
2849 const uint8_t *arg_bytes = arg;
2850 uint16_t byte_offset = 0;
2851
2852 if (!is_signed) return INT8_C(0);
2853#if zig_little_endian
2854 byte_offset = zig_int_bytes(bits) - 1;
2855#endif
2856 return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7));
2857}
2858
2859static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) {
2860 uint8_t *res_bytes = res;
2861 const uint8_t *arg_bytes = arg;
2862 uint16_t res_size = zig_int_bytes(res_bits);
2863 uint16_t arg_size = zig_int_bytes(arg_bits);
2864 uint16_t copy_size = zig_min_u16(res_size, arg_size);
2865 uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8));
2866
2867#if zig_little_endian
2868 memcpy(&res_bytes[0], &arg_bytes[0], copy_size);
2869 memset(&res_bytes[copy_size], sign_fill, res_size - copy_size);
2870#else
2871 memset(&res_bytes[0], sign_fill, res_size - copy_size);
2872 memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size);
2873#endif
2874}
2875
2876static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) {
2877 uint8_t *res_bytes = res;
2878 const uint8_t *arg_bytes = arg;
2879 uint16_t res_size = zig_int_bytes(res_bits);
2880
2881 if (res_is_signed != arg_is_signed) zig_unreachable();
2882 if (res_bits > arg_bits) zig_unreachable();
2883
2884 if (res_is_signed) {
2885 uint16_t arg_byte_offset = UINT16_C(0);
2886
2887#if zig_big_endian
2888 arg_byte_offset = zig_int_bytes(arg_bits) - res_size;
2889#endif
2890
2891 memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size);
2892 } else {
2893 uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3));
2894 uint16_t arg_byte_offset = res_byte_offset;
2895
2896#if zig_little_endian
2897 memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset);
2898#else
2899 res_byte_offset = res_size - UINT16_C(1) - res_byte_offset;
2900 arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset;
2901
2902 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
2903#endif
2904
2905 res_bytes[res_byte_offset] = zig_u8_truncate_u8(
2906 arg_bytes[arg_byte_offset],
2907 zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1)
2908 );
2909 res_byte_offset += UINT16_C(1);
2910 arg_byte_offset += UINT16_C(1);
2911
2912#if zig_little_endian
2913 memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset);
2914#else
2915 memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset);
2916#endif
2917 }
2918}
2919
2920#define zig_big_casts(is, s, w, IntType) \
2921 static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \
2922 IntType res; \
2923 zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \
2924 return res; \
2925 } \
2926\
2927 static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2928 zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \
2929 } \
2930\
2931 static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \
2932 IntType res; \
2933 zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \
2934 return res; \
2935 } \
2936\
2937 static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2938 zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \
2939 }
2940zig_big_casts(false, u, 8, uint8_t)
2941zig_big_casts(true , i, 8, int8_t)
2942zig_big_casts(false, u, 16, uint16_t)
2943zig_big_casts(true , i, 16, int16_t)
2944zig_big_casts(false, u, 32, uint32_t)
2945zig_big_casts(true , i, 32, int32_t)
2946zig_big_casts(false, u, 64, uint64_t)
2947zig_big_casts(true , i, 64, int64_t)
2948zig_big_casts(false, u, 128, zig_u128)
2949zig_big_casts(true , i, 128, zig_i128)
2950
2951static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) {
2952 uint8_t *res_bytes = res;
2953 const uint8_t *arg_bytes = arg;
2954 uint16_t size = zig_int_bytes(bits);
2955 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2956 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2957 uint8_t sign_byte;
2958 uint8_t fill_byte;
2959
2960#if zig_big_endian
2961 byte_offset = size - UINT16_C(1) - byte_offset;
2962#endif
2963
2964 if (res_is_signed) {
2965 int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2966
2967 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2968 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2969 } else {
2970 sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2971 fill_byte = UINT8_C(0);
2972 }
2973
2974#if zig_little_endian
2975 memcpy(&res_bytes[0], &arg_bytes[0], byte_offset);
2976 res_bytes[byte_offset] = sign_byte;
2977 byte_offset += UINT16_C(1);
2978 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2979#else
2980 memset(&res_bytes[0], fill_byte, byte_offset);
2981 res_bytes[byte_offset] = sign_byte;
2982 byte_offset += UINT16_C(1);
2983 memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset);
2984#endif
2985}
2986
2987static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) {
24212988 const uint8_t *lhs_bytes = lhs;
2422 const uint8_t *rhs_bytes = rhs;
24232989 uint16_t byte_offset = 0;
24242990 bool do_signed = is_signed;
24252991 uint16_t remaining_bytes = zig_int_bytes(bits);
......@@ -2429,6 +2995,7 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24292995#endif
24302996
24312997 while (remaining_bytes >= 128 / CHAR_BIT) {
2998 uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0);
24322999 int32_t limb_cmp;
24333000
24343001#if zig_little_endian
......@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24373004
24383005 if (do_signed) {
24393006 zig_i128 lhs_limb;
2440 zig_i128 rhs_limb;
3007 zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte);
24413008
24423009 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2443 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24443010 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
24453011 do_signed = false;
24463012 } else {
24473013 zig_u128 lhs_limb;
2448 zig_u128 rhs_limb;
3014 zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte);
24493015
24503016 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2451 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24523017 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
24533018 }
24543019
......@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24613026 }
24623027
24633028 while (remaining_bytes >= 64 / CHAR_BIT) {
3029 uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0);
3030
24643031#if zig_little_endian
24653032 byte_offset -= 64 / CHAR_BIT;
24663033#endif
24673034
24683035 if (do_signed) {
24693036 int64_t lhs_limb;
2470 int64_t rhs_limb;
3037 int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte);
24713038
24723039 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2473 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24743040 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24753041 do_signed = false;
24763042 } else {
24773043 uint64_t lhs_limb;
2478 uint64_t rhs_limb;
3044 uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte);
24793045
24803046 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2481 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24823047 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24833048 }
24843049
......@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24903055 }
24913056
24923057 while (remaining_bytes >= 32 / CHAR_BIT) {
3058 uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0);
3059
24933060#if zig_little_endian
24943061 byte_offset -= 32 / CHAR_BIT;
24953062#endif
24963063
24973064 if (do_signed) {
24983065 int32_t lhs_limb;
2499 int32_t rhs_limb;
3066 int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte);
25003067
25013068 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2502 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25033069 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25043070 do_signed = false;
25053071 } else {
25063072 uint32_t lhs_limb;
2507 uint32_t rhs_limb;
3073 uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte);
25083074
25093075 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2510 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25113076 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25123077 }
25133078
......@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25193084 }
25203085
25213086 while (remaining_bytes >= 16 / CHAR_BIT) {
3087 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3088
25223089#if zig_little_endian
25233090 byte_offset -= 16 / CHAR_BIT;
25243091#endif
25253092
25263093 if (do_signed) {
25273094 int16_t lhs_limb;
2528 int16_t rhs_limb;
3095 int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte);
25293096
25303097 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2531 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25323098 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25333099 do_signed = false;
25343100 } else {
25353101 uint16_t lhs_limb;
2536 uint16_t rhs_limb;
3102 uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte);
25373103
25383104 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2539 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25403105 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25413106 }
25423107
......@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25483113 }
25493114
25503115 while (remaining_bytes >= 8 / CHAR_BIT) {
3116 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3117
25513118#if zig_little_endian
25523119 byte_offset -= 8 / CHAR_BIT;
25533120#endif
25543121
25553122 if (do_signed) {
25563123 int8_t lhs_limb;
2557 int8_t rhs_limb;
3124 int16_t lhs_cmp_limb;
3125 int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte);
25583126
25593127 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2560 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2561 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3128 lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb);
3129 if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb);
25623130 do_signed = false;
25633131 } else {
25643132 uint8_t lhs_limb;
2565 uint8_t rhs_limb;
3133 uint8_t rhs_limb = rhs_byte;
25663134
25673135 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2568 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25693136 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25703137 }
25713138
......@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25793146 return 0;
25803147}
25813148
2582static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2583 uint8_t *res_bytes = res;
3149static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
25843150 const uint8_t *lhs_bytes = lhs;
25853151 const uint8_t *rhs_bytes = rhs;
25863152 uint16_t byte_offset = 0;
3153 bool do_signed = is_signed;
25873154 uint16_t remaining_bytes = zig_int_bytes(bits);
2588 (void)is_signed;
3155
3156#if zig_little_endian
3157 byte_offset = remaining_bytes;
3158#endif
25893159
25903160 while (remaining_bytes >= 128 / CHAR_BIT) {
2591 zig_u128 res_limb;
2592 zig_u128 lhs_limb;
2593 zig_u128 rhs_limb;
3161 int32_t limb_cmp;
25943162
2595 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2596 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2597 res_limb = zig_and_u128(lhs_limb, rhs_limb);
2598 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3163#if zig_little_endian
3164 byte_offset -= 128 / CHAR_BIT;
3165#endif
3166
3167 if (do_signed) {
3168 zig_i128 lhs_limb;
3169 zig_i128 rhs_limb;
3170
3171 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3172 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3173 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
3174 do_signed = false;
3175 } else {
3176 zig_u128 lhs_limb;
3177 zig_u128 rhs_limb;
3178
3179 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3180 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3181 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
3182 }
25993183
3184 if (limb_cmp != 0) return limb_cmp;
26003185 remaining_bytes -= 128 / CHAR_BIT;
3186
3187#if zig_big_endian
26013188 byte_offset += 128 / CHAR_BIT;
3189#endif
26023190 }
26033191
26043192 while (remaining_bytes >= 64 / CHAR_BIT) {
2605 uint64_t res_limb;
2606 uint64_t lhs_limb;
2607 uint64_t rhs_limb;
3193#if zig_little_endian
3194 byte_offset -= 64 / CHAR_BIT;
3195#endif
26083196
2609 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2610 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2611 res_limb = zig_and_u64(lhs_limb, rhs_limb);
2612 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3197 if (do_signed) {
3198 int64_t lhs_limb;
3199 int64_t rhs_limb;
3200
3201 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3202 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3203 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3204 do_signed = false;
3205 } else {
3206 uint64_t lhs_limb;
3207 uint64_t rhs_limb;
3208
3209 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3210 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3211 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3212 }
26133213
26143214 remaining_bytes -= 64 / CHAR_BIT;
3215
3216#if zig_big_endian
26153217 byte_offset += 64 / CHAR_BIT;
3218#endif
26163219 }
26173220
26183221 while (remaining_bytes >= 32 / CHAR_BIT) {
2619 uint32_t res_limb;
2620 uint32_t lhs_limb;
2621 uint32_t rhs_limb;
3222#if zig_little_endian
3223 byte_offset -= 32 / CHAR_BIT;
3224#endif
26223225
2623 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2624 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2625 res_limb = zig_and_u32(lhs_limb, rhs_limb);
2626 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3226 if (do_signed) {
3227 int32_t lhs_limb;
3228 int32_t rhs_limb;
3229
3230 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3231 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3232 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3233 do_signed = false;
3234 } else {
3235 uint32_t lhs_limb;
3236 uint32_t rhs_limb;
3237
3238 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3239 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3240 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3241 }
26273242
26283243 remaining_bytes -= 32 / CHAR_BIT;
3244
3245#if zig_big_endian
26293246 byte_offset += 32 / CHAR_BIT;
3247#endif
26303248 }
26313249
26323250 while (remaining_bytes >= 16 / CHAR_BIT) {
2633 uint16_t res_limb;
2634 uint16_t lhs_limb;
2635 uint16_t rhs_limb;
3251#if zig_little_endian
3252 byte_offset -= 16 / CHAR_BIT;
3253#endif
26363254
2637 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2638 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2639 res_limb = zig_and_u16(lhs_limb, rhs_limb);
2640 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3255 if (do_signed) {
3256 int16_t lhs_limb;
3257 int16_t rhs_limb;
3258
3259 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3260 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3261 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3262 do_signed = false;
3263 } else {
3264 uint16_t lhs_limb;
3265 uint16_t rhs_limb;
3266
3267 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3268 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3269 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3270 }
26413271
26423272 remaining_bytes -= 16 / CHAR_BIT;
3273
3274#if zig_big_endian
26433275 byte_offset += 16 / CHAR_BIT;
3276#endif
26443277 }
26453278
26463279 while (remaining_bytes >= 8 / CHAR_BIT) {
2647 uint8_t res_limb;
2648 uint8_t lhs_limb;
2649 uint8_t rhs_limb;
3280#if zig_little_endian
3281 byte_offset -= 8 / CHAR_BIT;
3282#endif
26503283
2651 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2652 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2653 res_limb = zig_and_u8(lhs_limb, rhs_limb);
2654 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3284 if (do_signed) {
3285 int8_t lhs_limb;
3286 int8_t rhs_limb;
3287
3288 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3289 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3290 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3291 do_signed = false;
3292 } else {
3293 uint8_t lhs_limb;
3294 uint8_t rhs_limb;
3295
3296 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3297 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3298 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3299 }
26553300
26563301 remaining_bytes -= 8 / CHAR_BIT;
3302
3303#if zig_big_endian
26573304 byte_offset += 8 / CHAR_BIT;
3305#endif
26583306 }
3307
3308 return 0;
26593309}
26603310
2661static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3311static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
26623312 uint8_t *res_bytes = res;
2663 const uint8_t *lhs_bytes = lhs;
2664 const uint8_t *rhs_bytes = rhs;
3313 const uint8_t *arg_bytes = arg;
26653314 uint16_t byte_offset = 0;
26663315 uint16_t remaining_bytes = zig_int_bytes(bits);
2667 (void)is_signed;
3316 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3317
3318#if zig_big_endian
3319 byte_offset = remaining_bytes;
3320#endif
26683321
26693322 while (remaining_bytes >= 128 / CHAR_BIT) {
2670 zig_u128 res_limb;
2671 zig_u128 lhs_limb;
2672 zig_u128 rhs_limb;
3323 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
26733324
2674 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2675 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2676 res_limb = zig_or_u128(lhs_limb, rhs_limb);
2677 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3325#if zig_big_endian
3326 byte_offset -= 128 / CHAR_BIT;
3327#endif
3328
3329 if (remaining_bytes != 128 / CHAR_BIT || is_signed) {
3330 zig_i128 res_limb;
3331 zig_i128 arg_limb;
3332
3333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3334 res_limb = zig_not_i128(arg_limb, limb_bits);
3335 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3336 } else {
3337 zig_u128 res_limb;
3338 zig_u128 arg_limb;
3339
3340 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3341 res_limb = zig_not_u128(arg_limb, limb_bits);
3342 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3343 }
26783344
26793345 remaining_bytes -= 128 / CHAR_BIT;
3346
3347#if zig_little_endian
26803348 byte_offset += 128 / CHAR_BIT;
3349#endif
26813350 }
26823351
26833352 while (remaining_bytes >= 64 / CHAR_BIT) {
2684 uint64_t res_limb;
2685 uint64_t lhs_limb;
2686 uint64_t rhs_limb;
3353 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
26873354
2688 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2689 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2690 res_limb = zig_or_u64(lhs_limb, rhs_limb);
2691 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3355#if zig_big_endian
3356 byte_offset -= 64 / CHAR_BIT;
3357#endif
3358
3359 if (remaining_bytes != 64 / CHAR_BIT || is_signed) {
3360 int64_t res_limb;
3361 int64_t arg_limb;
3362
3363 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3364 res_limb = zig_not_i64(arg_limb, limb_bits);
3365 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3366 } else {
3367 uint64_t res_limb;
3368 uint64_t arg_limb;
3369
3370 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3371 res_limb = zig_not_u64(arg_limb, limb_bits);
3372 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3373 }
26923374
26933375 remaining_bytes -= 64 / CHAR_BIT;
3376
3377#if zig_little_endian
26943378 byte_offset += 64 / CHAR_BIT;
3379#endif
26953380 }
26963381
26973382 while (remaining_bytes >= 32 / CHAR_BIT) {
2698 uint32_t res_limb;
2699 uint32_t lhs_limb;
2700 uint32_t rhs_limb;
3383 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
27013384
2702 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2703 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2704 res_limb = zig_or_u32(lhs_limb, rhs_limb);
2705 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3385#if zig_big_endian
3386 byte_offset -= 32 / CHAR_BIT;
3387#endif
3388
3389 if (remaining_bytes != 32 / CHAR_BIT || is_signed) {
3390 int32_t res_limb;
3391 int32_t arg_limb;
3392
3393 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3394 res_limb = zig_not_i32(arg_limb, limb_bits);
3395 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3396 } else {
3397 uint32_t res_limb;
3398 uint32_t arg_limb;
3399
3400 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3401 res_limb = zig_not_u32(arg_limb, limb_bits);
3402 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3403 }
27063404
27073405 remaining_bytes -= 32 / CHAR_BIT;
3406
3407#if zig_little_endian
27083408 byte_offset += 32 / CHAR_BIT;
3409#endif
27093410 }
27103411
27113412 while (remaining_bytes >= 16 / CHAR_BIT) {
2712 uint16_t res_limb;
2713 uint16_t lhs_limb;
2714 uint16_t rhs_limb;
3413 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
27153414
2716 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2717 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2718 res_limb = zig_or_u16(lhs_limb, rhs_limb);
2719 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3415#if zig_big_endian
3416 byte_offset -= 16 / CHAR_BIT;
3417#endif
27203418
2721 remaining_bytes -= 16 / CHAR_BIT;
2722 byte_offset += 16 / CHAR_BIT;
2723 }
3419 if (remaining_bytes != 16 / CHAR_BIT || is_signed) {
3420 int16_t res_limb;
3421 int16_t arg_limb;
3422
3423 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3424 res_limb = zig_not_i16(arg_limb, limb_bits);
3425 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3426 } else {
3427 uint16_t res_limb;
3428 uint16_t arg_limb;
3429
3430 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3431 res_limb = zig_not_u16(arg_limb, limb_bits);
3432 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3433 }
3434
3435 remaining_bytes -= 16 / CHAR_BIT;
3436
3437#if zig_little_endian
3438 byte_offset += 16 / CHAR_BIT;
3439#endif
3440 }
3441
3442 while (remaining_bytes >= 8 / CHAR_BIT) {
3443 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3444
3445#if zig_big_endian
3446 byte_offset -= 8 / CHAR_BIT;
3447#endif
3448
3449 if (remaining_bytes != 8 / CHAR_BIT || is_signed) {
3450 int8_t res_limb;
3451 int8_t arg_limb;
3452
3453 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3454 res_limb = zig_not_i8(arg_limb, limb_bits);
3455 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3456 } else {
3457 uint8_t res_limb;
3458 uint8_t arg_limb;
3459
3460 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3461 res_limb = zig_not_u8(arg_limb, limb_bits);
3462 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3463 }
3464
3465 remaining_bytes -= 8 / CHAR_BIT;
3466
3467#if zig_little_endian
3468 byte_offset += 8 / CHAR_BIT;
3469#endif
3470 }
3471}
3472
3473static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3474 uint8_t *res_bytes = res;
3475 const uint8_t *lhs_bytes = lhs;
3476 const uint8_t *rhs_bytes = rhs;
3477 uint16_t byte_offset = 0;
3478 uint16_t remaining_bytes = zig_int_bytes(bits);
3479 (void)is_signed;
3480
3481 while (remaining_bytes >= 128 / CHAR_BIT) {
3482 zig_u128 res_limb;
3483 zig_u128 lhs_limb;
3484 zig_u128 rhs_limb;
3485
3486 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3487 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3488 res_limb = zig_and_u128(lhs_limb, rhs_limb);
3489 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3490
3491 remaining_bytes -= 128 / CHAR_BIT;
3492 byte_offset += 128 / CHAR_BIT;
3493 }
3494
3495 while (remaining_bytes >= 64 / CHAR_BIT) {
3496 uint64_t res_limb;
3497 uint64_t lhs_limb;
3498 uint64_t rhs_limb;
3499
3500 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3501 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3502 res_limb = zig_and_u64(lhs_limb, rhs_limb);
3503 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3504
3505 remaining_bytes -= 64 / CHAR_BIT;
3506 byte_offset += 64 / CHAR_BIT;
3507 }
3508
3509 while (remaining_bytes >= 32 / CHAR_BIT) {
3510 uint32_t res_limb;
3511 uint32_t lhs_limb;
3512 uint32_t rhs_limb;
3513
3514 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3515 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3516 res_limb = zig_and_u32(lhs_limb, rhs_limb);
3517 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3518
3519 remaining_bytes -= 32 / CHAR_BIT;
3520 byte_offset += 32 / CHAR_BIT;
3521 }
3522
3523 while (remaining_bytes >= 16 / CHAR_BIT) {
3524 uint16_t res_limb;
3525 uint16_t lhs_limb;
3526 uint16_t rhs_limb;
3527
3528 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3529 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3530 res_limb = zig_and_u16(lhs_limb, rhs_limb);
3531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3532
3533 remaining_bytes -= 16 / CHAR_BIT;
3534 byte_offset += 16 / CHAR_BIT;
3535 }
3536
3537 while (remaining_bytes >= 8 / CHAR_BIT) {
3538 uint8_t res_limb;
3539 uint8_t lhs_limb;
3540 uint8_t rhs_limb;
3541
3542 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3543 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3544 res_limb = zig_and_u8(lhs_limb, rhs_limb);
3545 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3546
3547 remaining_bytes -= 8 / CHAR_BIT;
3548 byte_offset += 8 / CHAR_BIT;
3549 }
3550}
3551
3552static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3553 uint8_t *res_bytes = res;
3554 const uint8_t *lhs_bytes = lhs;
3555 const uint8_t *rhs_bytes = rhs;
3556 uint16_t byte_offset = 0;
3557 uint16_t remaining_bytes = zig_int_bytes(bits);
3558 (void)is_signed;
3559
3560 while (remaining_bytes >= 128 / CHAR_BIT) {
3561 zig_u128 res_limb;
3562 zig_u128 lhs_limb;
3563 zig_u128 rhs_limb;
3564
3565 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3566 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3567 res_limb = zig_or_u128(lhs_limb, rhs_limb);
3568 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3569
3570 remaining_bytes -= 128 / CHAR_BIT;
3571 byte_offset += 128 / CHAR_BIT;
3572 }
3573
3574 while (remaining_bytes >= 64 / CHAR_BIT) {
3575 uint64_t res_limb;
3576 uint64_t lhs_limb;
3577 uint64_t rhs_limb;
3578
3579 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3580 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3581 res_limb = zig_or_u64(lhs_limb, rhs_limb);
3582 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3583
3584 remaining_bytes -= 64 / CHAR_BIT;
3585 byte_offset += 64 / CHAR_BIT;
3586 }
3587
3588 while (remaining_bytes >= 32 / CHAR_BIT) {
3589 uint32_t res_limb;
3590 uint32_t lhs_limb;
3591 uint32_t rhs_limb;
3592
3593 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3594 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3595 res_limb = zig_or_u32(lhs_limb, rhs_limb);
3596 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3597
3598 remaining_bytes -= 32 / CHAR_BIT;
3599 byte_offset += 32 / CHAR_BIT;
3600 }
3601
3602 while (remaining_bytes >= 16 / CHAR_BIT) {
3603 uint16_t res_limb;
3604 uint16_t lhs_limb;
3605 uint16_t rhs_limb;
3606
3607 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3608 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3609 res_limb = zig_or_u16(lhs_limb, rhs_limb);
3610 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3611
3612 remaining_bytes -= 16 / CHAR_BIT;
3613 byte_offset += 16 / CHAR_BIT;
3614 }
27243615
27253616 while (remaining_bytes >= 8 / CHAR_BIT) {
27263617 uint8_t res_limb;
......@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool
28163707 }
28173708}
28183709
3710static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) {
3711 uint8_t *res_bytes = res;
3712 uint16_t byte_offset = 0;
3713 uint16_t remaining_bytes = zig_int_bytes(bits);
3714 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3715
3716#if zig_big_endian
3717 byte_offset = remaining_bytes;
3718#endif
3719
3720 while (remaining_bytes >= 128 / CHAR_BIT) {
3721 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3722
3723#if zig_big_endian
3724 byte_offset -= 128 / CHAR_BIT;
3725#endif
3726
3727 {
3728 zig_u128 res_limb;
3729 bool limb_overflow;
3730
3731 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3732 limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3733 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3734 if (!limb_overflow) return;
3735 }
3736
3737 remaining_bytes -= 128 / CHAR_BIT;
3738
3739#if zig_little_endian
3740 byte_offset += 128 / CHAR_BIT;
3741#endif
3742 }
3743
3744 while (remaining_bytes >= 64 / CHAR_BIT) {
3745 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3746
3747#if zig_big_endian
3748 byte_offset -= 64 / CHAR_BIT;
3749#endif
3750
3751 {
3752 uint64_t res_limb;
3753 bool limb_overflow;
3754
3755 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3756 limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3757 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3758 if (!limb_overflow) return;
3759 }
3760
3761 remaining_bytes -= 64 / CHAR_BIT;
3762
3763#if zig_little_endian
3764 byte_offset += 64 / CHAR_BIT;
3765#endif
3766 }
3767
3768 while (remaining_bytes >= 32 / CHAR_BIT) {
3769 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3770
3771#if zig_big_endian
3772 byte_offset -= 32 / CHAR_BIT;
3773#endif
3774
3775 {
3776 uint32_t res_limb;
3777 bool limb_overflow;
3778
3779 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3780 limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3781 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3782 if (!limb_overflow) return;
3783 }
3784
3785 remaining_bytes -= 32 / CHAR_BIT;
3786
3787#if zig_little_endian
3788 byte_offset += 32 / CHAR_BIT;
3789#endif
3790 }
3791
3792 while (remaining_bytes >= 16 / CHAR_BIT) {
3793 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3794
3795#if zig_big_endian
3796 byte_offset -= 16 / CHAR_BIT;
3797#endif
3798
3799 {
3800 uint16_t res_limb;
3801 bool limb_overflow;
3802
3803 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3804 limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3805 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3806 if (!limb_overflow) return;
3807 }
3808
3809 remaining_bytes -= 16 / CHAR_BIT;
3810
3811#if zig_little_endian
3812 byte_offset += 16 / CHAR_BIT;
3813#endif
3814 }
3815
3816 while (remaining_bytes >= 8 / CHAR_BIT) {
3817 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3818
3819#if zig_big_endian
3820 byte_offset -= 8 / CHAR_BIT;
3821#endif
3822
3823 {
3824 uint8_t res_limb;
3825 bool limb_overflow;
3826
3827 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3828 limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3829 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3830 if (!limb_overflow) return;
3831 }
3832
3833 remaining_bytes -= 8 / CHAR_BIT;
3834
3835#if zig_little_endian
3836 byte_offset += 8 / CHAR_BIT;
3837#endif
3838 }
3839}
3840
3841static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) {
3842 uint8_t *res_bytes = res;
3843 uint16_t byte_offset = 0;
3844 uint16_t remaining_bytes = zig_int_bytes(bits);
3845 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3846
3847#if zig_big_endian
3848 byte_offset = remaining_bytes;
3849#endif
3850
3851 while (remaining_bytes >= 128 / CHAR_BIT) {
3852 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3853
3854#if zig_big_endian
3855 byte_offset -= 128 / CHAR_BIT;
3856#endif
3857
3858 {
3859 zig_u128 res_limb;
3860 bool limb_overflow;
3861
3862 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3863 limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3864 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3865 if (!limb_overflow) return;
3866 }
3867
3868 remaining_bytes -= 128 / CHAR_BIT;
3869
3870#if zig_little_endian
3871 byte_offset += 128 / CHAR_BIT;
3872#endif
3873 }
3874
3875 while (remaining_bytes >= 64 / CHAR_BIT) {
3876 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3877
3878#if zig_big_endian
3879 byte_offset -= 64 / CHAR_BIT;
3880#endif
3881
3882 {
3883 uint64_t res_limb;
3884 bool limb_overflow;
3885
3886 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3887 limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3888 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3889 if (!limb_overflow) return;
3890 }
3891
3892 remaining_bytes -= 64 / CHAR_BIT;
3893
3894#if zig_little_endian
3895 byte_offset += 64 / CHAR_BIT;
3896#endif
3897 }
3898
3899 while (remaining_bytes >= 32 / CHAR_BIT) {
3900 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3901
3902#if zig_big_endian
3903 byte_offset -= 32 / CHAR_BIT;
3904#endif
3905
3906 {
3907 uint32_t res_limb;
3908 bool limb_overflow;
3909
3910 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3911 limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3912 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3913 if (!limb_overflow) return;
3914 }
3915
3916 remaining_bytes -= 32 / CHAR_BIT;
3917
3918#if zig_little_endian
3919 byte_offset += 32 / CHAR_BIT;
3920#endif
3921 }
3922
3923 while (remaining_bytes >= 16 / CHAR_BIT) {
3924 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3925
3926#if zig_big_endian
3927 byte_offset -= 16 / CHAR_BIT;
3928#endif
3929
3930 {
3931 uint16_t res_limb;
3932 bool limb_overflow;
3933
3934 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3935 limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3936 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3937 if (!limb_overflow) return;
3938 }
3939
3940 remaining_bytes -= 16 / CHAR_BIT;
3941
3942#if zig_little_endian
3943 byte_offset += 16 / CHAR_BIT;
3944#endif
3945 }
3946
3947 while (remaining_bytes >= 8 / CHAR_BIT) {
3948 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3949
3950#if zig_big_endian
3951 byte_offset -= 8 / CHAR_BIT;
3952#endif
3953
3954 {
3955 uint8_t res_limb;
3956 bool limb_overflow;
3957
3958 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3959 limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3960 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3961 if (!limb_overflow) return;
3962 }
3963
3964 remaining_bytes -= 8 / CHAR_BIT;
3965
3966#if zig_little_endian
3967 byte_offset += 8 / CHAR_BIT;
3968#endif
3969 }
3970}
3971
3972static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
3973 uint8_t *res_bytes = res;
3974 const uint8_t *arg_bytes = arg;
3975 uint16_t byte_offset = 0;
3976 uint16_t remaining_bytes = zig_int_bytes(bits);
3977 if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) {
3978 memcpy(res, arg, remaining_bytes);
3979 return;
3980 }
3981 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3982 bool overflow = true;
3983
3984#if zig_big_endian
3985 byte_offset = remaining_bytes;
3986#endif
3987
3988 while (remaining_bytes >= 128 / CHAR_BIT) {
3989 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3990
3991#if zig_big_endian
3992 byte_offset -= 128 / CHAR_BIT;
3993#endif
3994
3995 {
3996 zig_u128 res_limb;
3997 zig_u128 arg_limb;
3998
3999 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4000 overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
4001 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4002 }
4003
4004 remaining_bytes -= 128 / CHAR_BIT;
4005
4006#if zig_little_endian
4007 byte_offset += 128 / CHAR_BIT;
4008#endif
4009 }
4010
4011 while (remaining_bytes >= 64 / CHAR_BIT) {
4012 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
4013
4014#if zig_big_endian
4015 byte_offset -= 64 / CHAR_BIT;
4016#endif
4017
4018 {
4019 uint64_t res_limb;
4020 uint64_t arg_limb;
4021
4022 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4023 overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
4024 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4025 }
4026
4027 remaining_bytes -= 64 / CHAR_BIT;
4028
4029#if zig_little_endian
4030 byte_offset += 64 / CHAR_BIT;
4031#endif
4032 }
4033
4034 while (remaining_bytes >= 32 / CHAR_BIT) {
4035 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
4036
4037#if zig_big_endian
4038 byte_offset -= 32 / CHAR_BIT;
4039#endif
4040
4041 {
4042 uint32_t res_limb;
4043 uint32_t arg_limb;
4044
4045 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4046 overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
4047 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4048 }
4049
4050 remaining_bytes -= 32 / CHAR_BIT;
4051
4052#if zig_little_endian
4053 byte_offset += 32 / CHAR_BIT;
4054#endif
4055 }
4056
4057 while (remaining_bytes >= 16 / CHAR_BIT) {
4058 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
4059
4060#if zig_big_endian
4061 byte_offset -= 16 / CHAR_BIT;
4062#endif
4063
4064 {
4065 uint16_t res_limb;
4066 uint16_t arg_limb;
4067
4068 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4069 overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
4070 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4071 }
4072
4073 remaining_bytes -= 16 / CHAR_BIT;
4074
4075#if zig_little_endian
4076 byte_offset += 16 / CHAR_BIT;
4077#endif
4078 }
4079
4080 while (remaining_bytes >= 8 / CHAR_BIT) {
4081 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
4082
4083#if zig_big_endian
4084 byte_offset -= 8 / CHAR_BIT;
4085#endif
4086
4087 {
4088 uint8_t res_limb;
4089 uint8_t arg_limb;
4090
4091 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4092 overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
4093 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4094 }
4095
4096 remaining_bytes -= 8 / CHAR_BIT;
4097
4098#if zig_little_endian
4099 byte_offset += 8 / CHAR_BIT;
4100#endif
4101 }
4102}
4103
4104static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4105 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4106}
4107
4108static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4109 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4110}
4111
28194112static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
28204113 uint8_t *res_bytes = res;
28214114 const uint8_t *lhs_bytes = lhs;
28224115 const uint8_t *rhs_bytes = rhs;
28234116 uint16_t byte_offset = 0;
28244117 uint16_t remaining_bytes = zig_int_bytes(bits);
2825 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4118 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
28264119 bool overflow = false;
28274120
28284121#if zig_big_endian
......@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
30384331 const uint8_t *rhs_bytes = rhs;
30394332 uint16_t byte_offset = 0;
30404333 uint16_t remaining_bytes = zig_int_bytes(bits);
3041 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4334 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
30424335 bool overflow = false;
30434336
30444337#if zig_big_endian
......@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
32384531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
32394532 }
32404533
3241 remaining_bytes -= 8 / CHAR_BIT;
4534 remaining_bytes -= 8 / CHAR_BIT;
4535
4536#if zig_little_endian
4537 byte_offset += 8 / CHAR_BIT;
4538#endif
4539 }
4540
4541 return overflow;
4542}
4543
4544static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4545 if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4546}
4547
4548static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4549 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
4550}
4551
4552static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4553 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits);
4554
4555 if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return;
4556 switch (sat_sign) {
4557 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4558 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4559 }
4560}
4561
4562static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4563 if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4564}
4565
4566static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4567 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
4568}
4569
4570static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4571 int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1);
4572
4573 if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return;
4574 switch (sat_sign) {
4575 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4576 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4577 }
4578}
4579
4580static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4581 uint8_t *res_bytes = res;
4582 const uint8_t *lhs_bytes = lhs;
4583 const uint8_t *rhs_bytes = rhs;
4584 uint16_t size = zig_int_bytes(bits);
4585 uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4586 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4587 uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8));
4588 uint16_t lhs_byte_offset = sign_byte_offset;
4589 uint16_t lhs_end_byte_offset = UINT16_C(0);
4590 bool overflow = false;
4591
4592#if zig_big_endian
4593 lhs_byte_offset = size - lhs_byte_offset;
4594 lhs_end_byte_offset = size - lhs_end_byte_offset;
4595#endif
4596
4597 while (lhs_byte_offset != lhs_end_byte_offset) {
4598 uint16_t rhs_byte_offset = UINT16_C(0);
4599 uint16_t end_byte_offset = sign_byte_offset;
4600 uint16_t res_byte_offset;
4601 uint16_t lhs_byte;
4602 uint8_t res_byte = UINT8_C(0);
4603 uint16_t mul_res = UINT16_C(0);
4604 uint8_t carry = UINT8_C(0);
4605
4606#if zig_little_endian
4607 lhs_byte_offset -= UINT16_C(1);
4608#else
4609 rhs_byte_offset = size - rhs_byte_offset;
4610 end_byte_offset = size - end_byte_offset;
4611#endif
4612
4613 lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill;
4614
4615#if zig_big_endian
4616 lhs_byte_offset += UINT16_C(1);
4617#endif
4618
4619 res_byte_offset = lhs_byte_offset;
4620
4621 while (res_byte_offset != end_byte_offset) {
4622 bool res_byte_initialized = res_byte_offset != lhs_byte_offset;
4623
4624#if zig_big_endian
4625 rhs_byte_offset -= UINT16_C(1);
4626 res_byte_offset -= UINT16_C(1);
4627#endif
4628
4629 if (res_byte_initialized) res_byte = res_bytes[res_byte_offset];
4630 carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8));
4631 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16(
4632 zig_shr_u16(mul_res, UINT8_C(8))
4633 ), UINT8_C(8));
4634 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4635 carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16(
4636 mul_res,
4637 UINT8_C(8)
4638 ), UINT8_C(8));
4639
4640#if zig_little_endian
4641 rhs_byte_offset += UINT16_C(1);
4642 res_byte_offset += UINT16_C(1);
4643#endif
4644 }
4645
4646 while (rhs_byte_offset != end_byte_offset) {
4647#if zig_big_endian
4648 rhs_byte_offset -= UINT16_C(1);
4649#endif
4650
4651 carry = zig_addo_u8(
4652 &res_byte,
4653 zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))),
4654 carry,
4655 UINT8_C(8)
4656 );
4657 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4658 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16(
4659 mul_res,
4660 UINT8_C(8)
4661 ), UINT8_C(8));
4662 overflow |= res_byte != UINT8_C(0);
4663
4664#if zig_little_endian
4665 rhs_byte_offset += UINT16_C(1);
4666#endif
4667 }
4668
4669 overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0);
4670 overflow |= carry != UINT8_C(0);
4671 }
4672
4673#if zig_little_endian
4674 sign_byte_offset -= UINT64_C(1);
4675#else
4676 sign_byte_offset = size - sign_byte_offset;
4677#endif
4678
4679 if (lhs_sign_fill != rhs_sign_fill) {
4680 uint16_t byte_offset = UINT16_C(0);
4681 uint16_t end_byte_offset = sign_byte_offset;
4682 uint8_t res_byte;
4683 int8_t signed_res_byte;
4684 uint8_t carry = UINT8_C(0);
4685
4686#if zig_big_endian
4687 byte_offset = size - byte_offset;
4688 end_byte_offset += UINT16_C(1);
4689#endif
4690
4691 while (byte_offset != end_byte_offset) {
4692#if zig_big_endian
4693 byte_offset -= UINT16_C(1);
4694#endif
4695
4696 carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8));
4697 carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8));
4698 carry += zig_subo_u8(
4699 &res_bytes[byte_offset],
4700 res_byte,
4701 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4702 UINT8_C(8)
4703 );
4704
4705#if zig_little_endian
4706 byte_offset += UINT16_C(1);
4707#endif
4708 }
4709
4710#if zig_big_endian
4711 byte_offset -= UINT16_C(1);
4712#endif
4713
4714 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4715 overflow |= signed_res_byte < INT8_C(0);
4716 overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8));
4717 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4718 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4719 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4720 UINT8_C(8)
4721 ), UINT8_C(8));
4722 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4723 } else if (lhs_sign_fill != UINT8_C(0)) {
4724 uint16_t byte_offset = UINT16_C(0);
4725 uint16_t end_byte_offset = sign_byte_offset;
4726 uint8_t res_byte;
4727 int8_t signed_res_byte;
4728 uint8_t carry = UINT8_C(1);
4729
4730#if zig_big_endian
4731 byte_offset = size - byte_offset;
4732 end_byte_offset += UINT16_C(1);
4733#endif
4734
4735 while (byte_offset != end_byte_offset) {
4736#if zig_big_endian
4737 byte_offset -= UINT16_C(1);
4738#endif
4739
4740 carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8));
4741 carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8));
4742 carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8));
4743
4744#if zig_little_endian
4745 byte_offset += UINT16_C(1);
4746#endif
4747 }
4748
4749#if zig_big_endian
4750 byte_offset -= UINT16_C(1);
4751#endif
4752
4753 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4754 overflow |= signed_res_byte < INT8_C(0);
4755 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4756 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4757 lhs_bytes[byte_offset],
4758 UINT8_C(8)
4759 ), UINT8_C(8));
4760 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4761 rhs_bytes[byte_offset],
4762 UINT8_C(8)
4763 ), UINT8_C(8));
4764 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4765 } else if (is_signed) {
4766 int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4767
4768 overflow |= signed_res_byte < INT8_C(0);
4769 }
4770
4771 {
4772 uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4773 uint8_t fill_byte = UINT8_C(0);
4774
4775 if (is_signed) {
4776 int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4777 int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits);
4778
4779 overflow |= sign_byte != truncated;
4780 res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
4781 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
4782 } else {
4783 uint8_t sign_byte = res_bytes[sign_byte_offset];
4784 uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits);
4785
4786 overflow |= sign_byte != truncated;
4787 res_bytes[sign_byte_offset] = truncated;
4788 }
4789
4790#if zig_little_endian
4791 sign_byte_offset += UINT16_C(1);
4792 memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset);
4793#else
4794 memset(&res_bytes[0], fill_byte, sign_byte_offset);
4795#endif
4796 }
4797
4798 return overflow;
4799}
4800
4801static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4802 if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4803}
4804
4805static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4806 (void)zig_mulo_big(res, lhs, rhs, is_signed, bits);
4807}
4808
4809static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4810 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits);
4811
4812 if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return;
4813 switch (sat_sign) {
4814 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4815 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4816 }
4817}
4818
4819static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4820 if (is_signed) {
4821 zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4822 __divei5(res, lhs, rhs, temp, bits);
4823 } else {
4824 zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4825 __udivei5(res, lhs, rhs, temp, bits);
4826 }
4827}
4828
4829static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4830 if (is_signed) {
4831 zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4832 __modei5(res, lhs, rhs, temp, bits);
4833 } else {
4834 zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4835 __umodei5(res, lhs, rhs, temp, bits);
4836 }
4837}
4838
4839static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4840 bool decrement = false;
4841
4842 if (is_signed) {
4843 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4844 decrement = zig_u32_bitCast_i32(zig_xor_i32(
4845 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4846 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4847 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32));
4848 }
4849 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4850 if (decrement) zig_decrement_big(res, is_signed, bits);
4851}
4852
4853static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4854 bool increment = false;
4855
4856 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4857 increment = zig_xor_i32(
4858 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4859 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4860 ) > INT32_C(0);
4861 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4862 if (increment) zig_increment_big(res, is_signed, bits);
4863}
4864
4865static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4866 bool fixup = false;
4867
4868 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4869 if (is_signed && zig_u32_bitCast_i32(zig_xor_i32(
4870 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4871 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4872 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits);
4873}
4874
4875static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4876 uint8_t *res_bytes = res;
4877 const uint8_t *lhs_bytes = lhs;
4878 uint16_t size = zig_int_bytes(bits);
4879 uint16_t res_byte_offset = UINT16_C(0);
4880 uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3));
4881 uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4882 uint8_t lhs_prev_byte;
4883 uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3));
4884
4885#if zig_big_endian
4886 res_byte_offset = size - res_byte_offset;
4887 lhs_byte_offset = size - lhs_byte_offset;
4888 end_byte_offset = size - end_byte_offset;
4889#endif
4890
4891 {
4892#if zig_big_endian
4893 lhs_byte_offset -= UINT16_C(1);
4894#endif
4895
4896 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4897
4898#if zig_little_endian
4899 lhs_byte_offset += UINT16_C(1);
4900#endif
4901 }
4902
4903 while (lhs_byte_offset != end_byte_offset) {
4904#if zig_big_endian
4905 res_byte_offset -= UINT16_C(1);
4906 lhs_byte_offset -= UINT16_C(1);
4907#endif
4908
4909 {
4910 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
4911
4912 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
4913 zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)),
4914 zig_u16_intCast_u8(lhs_prev_byte)
4915 ), byte_shift));
4916 lhs_prev_byte = lhs_byte;
4917 }
4918
4919#if zig_little_endian
4920 res_byte_offset += UINT16_C(1);
4921 lhs_byte_offset += UINT16_C(1);
4922#endif
4923 }
4924
4925 {
4926 uint8_t lhs_sign_fill = UINT8_C(0);
4927
4928#if zig_big_endian
4929 res_byte_offset -= UINT16_C(1);
4930#endif
4931
4932 if (is_signed) {
4933 int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8));
4934
4935 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
4936 lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
4937 } else {
4938 res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift);
4939 }
4940
4941#if zig_little_endian
4942 res_byte_offset += UINT16_C(1);
4943 memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset);
4944#else
4945 memset(&res_bytes[0], lhs_sign_fill, res_byte_offset);
4946#endif
4947 }
4948}
4949
4950static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4951 uint8_t *res_bytes = res;
4952 const uint8_t *lhs_bytes = lhs;
4953 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4954 uint16_t size = zig_int_bytes(bits);
4955 uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4956 uint16_t lhs_byte_offset = UINT16_C(0);
4957 uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3));
4958 uint8_t lhs_prev_byte = lhs_sign_fill;
4959 uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3));
4960 bool overflow = false;
4961
4962#if zig_little_endian
4963 lhs_byte_offset = size - lhs_byte_offset;
4964#else
4965 res_byte_offset = size - res_byte_offset;
4966 end_byte_offset = size - end_byte_offset;
4967#endif
4968
4969 while (lhs_byte_offset != end_byte_offset) {
4970#if zig_little_endian
4971 lhs_byte_offset -= UINT16_C(1);
4972#endif
4973
4974 overflow |= lhs_prev_byte != lhs_sign_fill;
4975 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4976
4977#if zig_big_endian
4978 lhs_byte_offset += UINT16_C(1);
4979#endif
4980 }
4981
4982#if zig_little_endian
4983 end_byte_offset = UINT16_C(0);
4984#else
4985 end_byte_offset = size;
4986#endif
4987
4988 {
4989 bool lhs_more_bytes = lhs_byte_offset != end_byte_offset;
4990
4991#if zig_little_endian
4992 if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1);
4993#endif
4994
4995 {
4996 uint8_t lhs_byte = UINT8_C(0);
4997
4998 if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset];
4999
5000 if (is_signed) {
5001 int16_t shifted = zig_shr_i16(zig_or_i16(
5002 zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5003 zig_i16_intCast_u8(lhs_byte)
5004 ), byte_shift);
5005 int8_t truncated = zig_i8_truncate_i16(
5006 shifted,
5007 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5008 );
5009 uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
5010
5011 overflow |= zig_i16_intCast_i8(truncated) != shifted;
5012#if zig_little_endian
5013 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5014 res_byte_offset -= UINT16_C(1);
5015#else
5016 memset(&res_bytes[0], fill, res_byte_offset);
5017#endif
5018 res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
5019 } else {
5020 uint16_t shifted = zig_shr_u16(zig_or_u16(
5021 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5022 zig_u16_intCast_u8(lhs_byte)
5023 ), byte_shift);
5024 uint8_t truncated = zig_u8_truncate_u16(
5025 shifted,
5026 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5027 );
5028
5029 overflow |= zig_u16_intCast_u8(truncated) != shifted;
5030#if zig_little_endian
5031 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5032 res_byte_offset -= UINT16_C(1);
5033#else
5034 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5035#endif
5036 res_bytes[res_byte_offset] = truncated;
5037 }
5038
5039 lhs_prev_byte = lhs_byte;
5040 }
5041
5042#if zig_big_endian
5043 res_byte_offset += UINT16_C(1);
5044 if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1);
5045#endif
5046 }
5047
5048 while (lhs_byte_offset != end_byte_offset) {
5049#if zig_little_endian
5050 res_byte_offset -= UINT16_C(1);
5051 lhs_byte_offset -= UINT16_C(1);
5052#endif
5053
5054 {
5055 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
5056
5057 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5058 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5059 zig_u16_intCast_u8(lhs_byte)
5060 ), byte_shift));
5061 lhs_prev_byte = lhs_byte;
5062 }
5063
5064#if zig_big_endian
5065 res_byte_offset += UINT16_C(1);
5066 lhs_byte_offset += UINT16_C(1);
5067#endif
5068 }
5069
5070 {
5071#if zig_little_endian
5072 res_byte_offset -= UINT16_C(1);
5073#endif
5074
5075 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(
5076 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5077 byte_shift
5078 ));
5079
5080#if zig_big_endian
5081 res_byte_offset += UINT16_C(1);
5082#endif
5083 }
5084
5085#if zig_little_endian
5086 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5087#else
5088 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5089#endif
5090
5091 return overflow;
5092}
5093
5094static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5095 if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits
5096}
5097
5098static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5099 (void)zig_shlo_big(res, lhs, rhs, is_signed, bits);
5100}
5101
5102#define zig_big_shls_builtin(w) \
5103 static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \
5104 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5105 uint##w##_t res; \
5106 const uint8_t *rhs_bytes = rhs; \
5107 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5108 !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5109 return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \
5110 } \
5111\
5112 static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \
5113 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5114 int##w##_t res; \
5115 const uint8_t *rhs_bytes = rhs; \
5116 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5117 !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5118 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
5119 lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \
5120 } \
5121\
5122 static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \
5123 const uint8_t *lhs_bytes = lhs; \
5124 if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \
5125 switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \
5126 case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \
5127 case INT32_C(0): return zig_minInt_big(res, false, bits); \
5128 case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \
5129 default: zig_unreachable(); \
5130 } \
5131 }
5132zig_big_shls_builtin(8)
5133zig_big_shls_builtin(16)
5134zig_big_shls_builtin(32)
5135zig_big_shls_builtin(64)
5136
5137static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5138 uint8_t *res_bytes = res;
5139 const uint8_t *arg_bytes = arg;
5140 uint16_t res_byte_offset = UINT16_C(0);
5141 uint16_t arg_byte_offset = bits / CHAR_BIT;
5142 uint16_t end_byte_offset = UINT16_C(1);
5143 uint16_t size = zig_int_bytes(bits);
5144
5145#if zig_big_endian
5146 res_byte_offset = size - res_byte_offset;
5147 arg_byte_offset = size - arg_byte_offset;
5148 end_byte_offset = size - end_byte_offset;
5149#endif
5150
5151 while (arg_byte_offset != end_byte_offset) {
5152#if zig_little_endian
5153 arg_byte_offset -= UINT16_C(1);
5154#else
5155 res_byte_offset -= UINT16_C(1);
5156#endif
5157
5158 res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset];
32425159
32435160#if zig_little_endian
3244 byte_offset += 8 / CHAR_BIT;
5161 res_byte_offset += UINT16_C(1);
5162#else
5163 arg_byte_offset += UINT16_C(1);
32455164#endif
32465165 }
32475166
3248 return overflow;
3249}
5167 {
5168#if zig_little_endian
5169 arg_byte_offset -= UINT16_C(1);
5170#else
5171 res_byte_offset -= UINT16_C(1);
5172#endif
32505173
3251static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3252 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
3253}
5174 {
5175 uint8_t byte = arg_bytes[arg_byte_offset];
5176 uint8_t fill = is_signed
5177 ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8))
5178 : UINT8_C(0);
32545179
3255static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3256 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
3257}
5180 res_bytes[res_byte_offset] = byte;
32585181
3259zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3260static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3261 if (!is_signed) {
3262 __udivei4(res, lhs, rhs, bits);
3263 return;
5182#if zig_little_endian
5183 res_byte_offset += UINT16_C(1);
5184 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5185#else
5186 memset(&res_bytes[0], fill, res_byte_offset);
5187#endif
5188 }
32645189 }
3265
3266 zig_trap();
32675190}
32685191
3269static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3270 if (!is_signed) {
3271 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
3272 return;
3273 }
5192static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5193 uint8_t *res_bytes = res;
5194 const uint8_t *arg_bytes = arg;
5195 uint16_t size = zig_int_bytes(bits);
5196 uint16_t res_byte_offset = UINT16_C(0);
5197 uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5198 uint16_t end_byte_offset = UINT16_C(0);
5199 uint8_t arg_prev_byte;
5200 uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3)));
32745201
3275 zig_trap();
3276}
5202#if zig_big_endian
5203 res_byte_offset = size - res_byte_offset;
5204 arg_byte_offset = size - arg_byte_offset;
5205 end_byte_offset = size - end_byte_offset;
5206#endif
32775207
3278static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3279 zig_trap();
3280}
5208 {
5209#if zig_little_endian
5210 arg_byte_offset -= UINT16_C(1);
5211#endif
32815212
3282zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3283static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3284 if (!is_signed) {
3285 __umodei4(res, lhs, rhs, bits);
3286 return;
5213 arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5214
5215#if zig_big_endian
5216 arg_byte_offset += UINT16_C(1);
5217#endif
32875218 }
32885219
3289 zig_trap();
3290}
5220 while (arg_byte_offset != end_byte_offset) {
5221#if zig_big_endian
5222 res_byte_offset -= UINT16_C(1);
5223#else
5224 arg_byte_offset -= UINT16_C(1);
5225#endif
32915226
3292static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3293 if (!is_signed) {
3294 zig_rem_big(res, lhs, rhs, is_signed, bits);
3295 return;
5227 {
5228 uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5229
5230 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5231 zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)),
5232 zig_u16_intCast_u8(arg_prev_byte)
5233 ), byte_shift));
5234 arg_prev_byte = arg_byte;
5235 }
5236
5237#if zig_little_endian
5238 res_byte_offset += UINT16_C(1);
5239#else
5240 arg_byte_offset += UINT16_C(1);
5241#endif
32965242 }
32975243
3298 zig_trap();
5244 {
5245 uint8_t arg_sign_fill = UINT8_C(0);
5246
5247#if zig_big_endian
5248 res_byte_offset -= UINT16_C(1);
5249#endif
5250
5251 if (is_signed) {
5252 int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8));
5253
5254 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
5255 arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
5256 } else {
5257 res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift);
5258 }
5259
5260#if zig_little_endian
5261 res_byte_offset += UINT16_C(1);
5262 memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset);
5263#else
5264 memset(&res_bytes[0], arg_sign_fill, res_byte_offset);
5265#endif
5266 }
32995267}
33005268
3301static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
3302 const uint8_t *val_bytes = val;
5269static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) {
5270 const uint8_t *arg_bytes = arg;
33035271 uint16_t byte_offset = 0;
3304 uint16_t remaining_bytes = zig_int_bytes(bits);
3305 uint16_t skip_bits = remaining_bytes * 8 - bits;
3306 uint16_t total_lz = 0;
3307 uint16_t limb_lz;
5272 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5273 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5274 uint16_t total_pc = 0;
33085275 (void)is_signed;
33095276
3310#if zig_little_endian
3311 byte_offset = remaining_bytes;
5277#if zig_big_endian
5278 byte_offset = zig_int_bytes(bits);
33125279#endif
33135280
33145281 while (remaining_bytes >= 128 / CHAR_BIT) {
3315#if zig_little_endian
5282 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5283
5284#if zig_big_endian
33165285 byte_offset -= 128 / CHAR_BIT;
33175286#endif
33185287
33195288 {
3320 zig_u128 val_limb;
5289 zig_u128 arg_limb;
33215290
3322 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3323 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);
5291 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5292 total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
33245293 }
33255294
3326 total_lz += limb_lz;
3327 if (limb_lz < 128 - skip_bits) return total_lz;
3328 skip_bits = 0;
33295295 remaining_bytes -= 128 / CHAR_BIT;
33305296
3331#if zig_big_endian
5297#if zig_little_endian
33325298 byte_offset += 128 / CHAR_BIT;
33335299#endif
33345300 }
33355301
33365302 while (remaining_bytes >= 64 / CHAR_BIT) {
3337#if zig_little_endian
5303 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5304
5305#if zig_big_endian
33385306 byte_offset -= 64 / CHAR_BIT;
33395307#endif
33405308
33415309 {
3342 uint64_t val_limb;
5310 uint64_t arg_limb;
33435311
3344 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3345 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);
5312 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5313 total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
33465314 }
33475315
3348 total_lz += limb_lz;
3349 if (limb_lz < 64 - skip_bits) return total_lz;
3350 skip_bits = 0;
33515316 remaining_bytes -= 64 / CHAR_BIT;
33525317
3353#if zig_big_endian
5318#if zig_little_endian
33545319 byte_offset += 64 / CHAR_BIT;
33555320#endif
33565321 }
33575322
33585323 while (remaining_bytes >= 32 / CHAR_BIT) {
3359#if zig_little_endian
5324 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5325
5326#if zig_big_endian
33605327 byte_offset -= 32 / CHAR_BIT;
33615328#endif
33625329
33635330 {
3364 uint32_t val_limb;
5331 uint32_t arg_limb;
33655332
3366 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3367 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);
5333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5334 total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
33685335 }
33695336
3370 total_lz += limb_lz;
3371 if (limb_lz < 32 - skip_bits) return total_lz;
3372 skip_bits = 0;
33735337 remaining_bytes -= 32 / CHAR_BIT;
33745338
3375#if zig_big_endian
5339#if zig_little_endian
33765340 byte_offset += 32 / CHAR_BIT;
33775341#endif
33785342 }
33795343
33805344 while (remaining_bytes >= 16 / CHAR_BIT) {
3381#if zig_little_endian
5345 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5346
5347#if zig_big_endian
33825348 byte_offset -= 16 / CHAR_BIT;
33835349#endif
33845350
33855351 {
3386 uint16_t val_limb;
5352 uint16_t arg_limb;
33875353
3388 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3389 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);
5354 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5355 total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
33905356 }
33915357
3392 total_lz += limb_lz;
3393 if (limb_lz < 16 - skip_bits) return total_lz;
3394 skip_bits = 0;
33955358 remaining_bytes -= 16 / CHAR_BIT;
33965359
3397#if zig_big_endian
5360#if zig_little_endian
33985361 byte_offset += 16 / CHAR_BIT;
33995362#endif
34005363 }
34015364
34025365 while (remaining_bytes >= 8 / CHAR_BIT) {
3403#if zig_little_endian
5366 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5367
5368#if zig_big_endian
34045369 byte_offset -= 8 / CHAR_BIT;
34055370#endif
34065371
34075372 {
3408 uint8_t val_limb;
5373 uint8_t arg_limb;
34095374
3410 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3411 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);
5375 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5376 total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
34125377 }
34135378
3414 total_lz += limb_lz;
3415 if (limb_lz < 8 - skip_bits) return total_lz;
3416 skip_bits = 0;
34175379 remaining_bytes -= 8 / CHAR_BIT;
34185380
3419#if zig_big_endian
5381#if zig_little_endian
34205382 byte_offset += 8 / CHAR_BIT;
34215383#endif
34225384 }
34235385
3424 return total_lz;
5386 return total_pc;
34255387}
34265388
3427static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {
3428 const uint8_t *val_bytes = val;
3429 uint16_t byte_offset = 0;
3430 uint16_t remaining_bytes = zig_int_bytes(bits);
3431 uint16_t total_tz = 0;
5389static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) {
5390 const uint8_t *arg_bytes = arg;
5391 uint16_t byte_offset = UINT16_C(0);
5392 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5393 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5394 uint16_t total_tz = UINT16_C(0);
34325395 uint16_t limb_tz;
34335396 (void)is_signed;
34345397
34355398#if zig_big_endian
3436 byte_offset = remaining_bytes;
5399 byte_offset = zig_int_bytes(bits);
34375400#endif
34385401
34395402 while (remaining_bytes >= 128 / CHAR_BIT) {
5403 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5404
34405405#if zig_big_endian
34415406 byte_offset -= 128 / CHAR_BIT;
34425407#endif
34435408
34445409 {
3445 zig_u128 val_limb;
5410 zig_u128 arg_limb;
34465411
3447 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3448 limb_tz = zig_ctz_u128(val_limb, 128);
5412 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5413 limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
34495414 }
34505415
34515416 total_tz += limb_tz;
3452 if (limb_tz < 128) return total_tz;
5417 if (limb_tz < limb_bits) return total_tz;
34535418 remaining_bytes -= 128 / CHAR_BIT;
34545419
34555420#if zig_little_endian
......@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34585423 }
34595424
34605425 while (remaining_bytes >= 64 / CHAR_BIT) {
5426 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5427
34615428#if zig_big_endian
34625429 byte_offset -= 64 / CHAR_BIT;
34635430#endif
34645431
34655432 {
3466 uint64_t val_limb;
5433 uint64_t arg_limb;
34675434
3468 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3469 limb_tz = zig_ctz_u64(val_limb, 64);
5435 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5436 limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
34705437 }
34715438
34725439 total_tz += limb_tz;
3473 if (limb_tz < 64) return total_tz;
5440 if (limb_tz < limb_bits) return total_tz;
34745441 remaining_bytes -= 64 / CHAR_BIT;
34755442
34765443#if zig_little_endian
......@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34795446 }
34805447
34815448 while (remaining_bytes >= 32 / CHAR_BIT) {
5449 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5450
34825451#if zig_big_endian
34835452 byte_offset -= 32 / CHAR_BIT;
34845453#endif
34855454
34865455 {
3487 uint32_t val_limb;
5456 uint32_t arg_limb;
34885457
3489 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3490 limb_tz = zig_ctz_u32(val_limb, 32);
5458 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5459 limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
34915460 }
34925461
34935462 total_tz += limb_tz;
3494 if (limb_tz < 32) return total_tz;
5463 if (limb_tz < limb_bits) return total_tz;
34955464 remaining_bytes -= 32 / CHAR_BIT;
34965465
34975466#if zig_little_endian
......@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35005469 }
35015470
35025471 while (remaining_bytes >= 16 / CHAR_BIT) {
5472 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5473
35035474#if zig_big_endian
35045475 byte_offset -= 16 / CHAR_BIT;
35055476#endif
35065477
35075478 {
3508 uint16_t val_limb;
5479 uint16_t arg_limb;
35095480
3510 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3511 limb_tz = zig_ctz_u16(val_limb, 16);
5481 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5482 limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
35125483 }
35135484
35145485 total_tz += limb_tz;
3515 if (limb_tz < 16) return total_tz;
5486 if (limb_tz < limb_bits) return total_tz;
35165487 remaining_bytes -= 16 / CHAR_BIT;
35175488
35185489#if zig_little_endian
......@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35215492 }
35225493
35235494 while (remaining_bytes >= 8 / CHAR_BIT) {
5495 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5496
35245497#if zig_big_endian
35255498 byte_offset -= 8 / CHAR_BIT;
35265499#endif
35275500
35285501 {
3529 uint8_t val_limb;
5502 uint8_t arg_limb;
35305503
3531 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3532 limb_tz = zig_ctz_u8(val_limb, 8);
5504 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5505 limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
35335506 }
35345507
35355508 total_tz += limb_tz;
3536 if (limb_tz < 8) return total_tz;
5509 if (limb_tz < limb_bits) return total_tz;
35375510 remaining_bytes -= 8 / CHAR_BIT;
35385511
35395512#if zig_little_endian
......@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35445517 return total_tz;
35455518}
35465519
3547static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {
3548 const uint8_t *val_bytes = val;
3549 uint16_t byte_offset = 0;
3550 uint16_t remaining_bytes = zig_int_bytes(bits);
3551 uint16_t total_pc = 0;
5520static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) {
5521 const uint8_t *arg_bytes = arg;
5522 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5523 uint16_t remaining_bytes = byte_offset;
5524 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5525 bool sign_limb = true;
5526 uint16_t total_lz = UINT16_C(0);
5527 uint16_t limb_lz;
35525528 (void)is_signed;
35535529
35545530#if zig_big_endian
3555 byte_offset = remaining_bytes;
5531 byte_offset = zig_int_bytes(bits) - remaining_bytes;
35565532#endif
35575533
35585534 while (remaining_bytes >= 128 / CHAR_BIT) {
3559#if zig_big_endian
5535 uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0));
5536
5537#if zig_little_endian
35605538 byte_offset -= 128 / CHAR_BIT;
35615539#endif
35625540
35635541 {
3564 zig_u128 val_limb;
5542 zig_u128 arg_limb;
35655543
3566 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3567 total_pc += zig_popcount_u128(val_limb, 128);
5544 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5545 limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
35685546 }
35695547
5548 total_lz += limb_lz;
5549 if (limb_lz < limb_bits) return total_lz;
5550 sign_limb = false;
35705551 remaining_bytes -= 128 / CHAR_BIT;
35715552
3572#if zig_little_endian
5553#if zig_big_endian
35735554 byte_offset += 128 / CHAR_BIT;
35745555#endif
35755556 }
35765557
35775558 while (remaining_bytes >= 64 / CHAR_BIT) {
3578#if zig_big_endian
5559 uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0));
5560
5561#if zig_little_endian
35795562 byte_offset -= 64 / CHAR_BIT;
35805563#endif
35815564
35825565 {
3583 uint64_t val_limb;
5566 uint64_t arg_limb;
35845567
3585 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3586 total_pc += zig_popcount_u64(val_limb, 64);
5568 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5569 limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
35875570 }
35885571
5572 total_lz += limb_lz;
5573 if (limb_lz < limb_bits) return total_lz;
5574 sign_limb = false;
35895575 remaining_bytes -= 64 / CHAR_BIT;
35905576
3591#if zig_little_endian
5577#if zig_big_endian
35925578 byte_offset += 64 / CHAR_BIT;
35935579#endif
35945580 }
35955581
35965582 while (remaining_bytes >= 32 / CHAR_BIT) {
3597#if zig_big_endian
5583 uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0));
5584
5585#if zig_little_endian
35985586 byte_offset -= 32 / CHAR_BIT;
35995587#endif
36005588
36015589 {
3602 uint32_t val_limb;
5590 uint32_t arg_limb;
36035591
3604 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3605 total_pc += zig_popcount_u32(val_limb, 32);
5592 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5593 limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
36065594 }
36075595
5596 total_lz += limb_lz;
5597 if (limb_lz < limb_bits) return total_lz;
5598 sign_limb = false;
36085599 remaining_bytes -= 32 / CHAR_BIT;
36095600
3610#if zig_little_endian
5601#if zig_big_endian
36115602 byte_offset += 32 / CHAR_BIT;
36125603#endif
36135604 }
36145605
36155606 while (remaining_bytes >= 16 / CHAR_BIT) {
3616#if zig_big_endian
5607 uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0));
5608
5609#if zig_little_endian
36175610 byte_offset -= 16 / CHAR_BIT;
36185611#endif
36195612
36205613 {
3621 uint16_t val_limb;
5614 uint16_t arg_limb;
36225615
3623 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3624 total_pc = zig_popcount_u16(val_limb, 16);
5616 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5617 limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
36255618 }
36265619
5620 total_lz += limb_lz;
5621 if (limb_lz < limb_bits) return total_lz;
5622 sign_limb = false;
36275623 remaining_bytes -= 16 / CHAR_BIT;
36285624
3629#if zig_little_endian
5625#if zig_big_endian
36305626 byte_offset += 16 / CHAR_BIT;
36315627#endif
36325628 }
36335629
36345630 while (remaining_bytes >= 8 / CHAR_BIT) {
3635#if zig_big_endian
5631 uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0));
5632
5633#if zig_little_endian
36365634 byte_offset -= 8 / CHAR_BIT;
36375635#endif
36385636
36395637 {
3640 uint8_t val_limb;
5638 uint8_t arg_limb;
36415639
3642 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3643 total_pc = zig_popcount_u8(val_limb, 8);
5640 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5641 limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
36445642 }
36455643
5644 total_lz += limb_lz;
5645 if (limb_lz < limb_bits) return total_lz;
5646 sign_limb = false;
36465647 remaining_bytes -= 8 / CHAR_BIT;
36475648
3648#if zig_little_endian
5649#if zig_big_endian
36495650 byte_offset += 8 / CHAR_BIT;
36505651#endif
36515652 }
36525653
3653 return total_pc;
5654 return total_lz;
36545655}
36555656
36565657/* ========================= Floating Point Support ========================= */
......@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);
36875688#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
36885689#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
36895690#else
3690#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)
3691#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)
3692#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)
3693#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)
3694#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)
5691#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr)
5692#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr)
5693#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr)
5694#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr)
5695#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr)
36955696#endif
36965697
36975698#define zig_has_f16 1
36985699#define zig_libc_name_f16(name) __##name##h
36995700#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
3700#if FLT_MANT_DIG == 11
5701#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11
37015702typedef float zig_f16;
37025703#define zig_make_f16(fp, repr) fp##f
3703#elif DBL_MANT_DIG == 11
5704#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11
37045705typedef double zig_f16;
37055706#define zig_make_f16(fp, repr) fp
3706#elif LDBL_MANT_DIG == 11
5707#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11
37075708typedef long double zig_f16;
37085709#define zig_make_f16(fp, repr) fp##l
3709#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
5710#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
37105711typedef _Float16 zig_f16;
37115712#define zig_make_f16(fp, repr) fp##f16
3712#elif defined(__SIZEOF_FP16__)
5713#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__)
37135714typedef __fp16 zig_f16;
37145715#define zig_make_f16(fp, repr) fp##f16
37155716#else
......@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;
37235724#undef zig_init_special_f16
37245725#define zig_init_special_f16(sign, name, arg, repr) repr
37255726#endif
3726#if defined(zig_darwin) && defined(zig_x86)
3727typedef uint16_t zig_compiler_rt_f16;
3728#else
3729typedef zig_f16 zig_compiler_rt_f16;
3730#endif
37315727
37325728#define zig_has_f32 1
37335729#define zig_libc_name_f32(name) name##f
......@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;
37365732#else
37375733#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
37385734#endif
3739#if FLT_MANT_DIG == 24
5735#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24
37405736typedef float zig_f32;
37415737#define zig_make_f32(fp, repr) fp##f
3742#elif DBL_MANT_DIG == 24
5738#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24
37435739typedef double zig_f32;
37445740#define zig_make_f32(fp, repr) fp
3745#elif LDBL_MANT_DIG == 24
5741#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24
37465742typedef long double zig_f32;
37475743#define zig_make_f32(fp, repr) fp##l
3748#elif FLT32_MANT_DIG == 24
5744#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24
37495745typedef _Float32 zig_f32;
37505746#define zig_make_f32(fp, repr) fp##f32
37515747#else
......@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;
37685764#else
37695765#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
37705766#endif
3771#if FLT_MANT_DIG == 53
5767#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53
37725768typedef float zig_f64;
37735769#define zig_make_f64(fp, repr) fp##f
3774#elif DBL_MANT_DIG == 53
5770#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53
37755771typedef double zig_f64;
37765772#define zig_make_f64(fp, repr) fp
3777#elif LDBL_MANT_DIG == 53
5773#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53
37785774typedef long double zig_f64;
37795775#define zig_make_f64(fp, repr) fp##l
3780#elif FLT64_MANT_DIG == 53
5776#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53
37815777typedef _Float64 zig_f64;
37825778#define zig_make_f64(fp, repr) fp##f64
3783#elif FLT32X_MANT_DIG == 53
5779#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53
37845780typedef _Float32x zig_f64;
37855781#define zig_make_f64(fp, repr) fp##f32x
37865782#else
......@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;
37985794#define zig_has_f80 1
37995795#define zig_libc_name_f80(name) __##name##x
38005796#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
3801#if FLT_MANT_DIG == 64
5797#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI
5798#undef zig_has_f80
5799typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80;
5800#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent }
5801#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5802#define zig_mantissa_repr_f80(arg) (arg).mantissa
5803#define zig_exponent_repr_f80(arg) (arg).exponent
5804#elif FLT_MANT_DIG == 64
38025805typedef float zig_f80;
38035806#define zig_make_f80(fp, repr) fp##f
38045807#elif DBL_MANT_DIG == 64
......@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;
38185821#define zig_make_f80(fp, repr) fp##l
38195822#else
38205823#undef zig_has_f80
3821#define zig_has_f80 0
3822#define zig_repr_f80 u128
38235824typedef zig_u128 zig_f80;
5825#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa)
5826#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa)
5827#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg)
5828#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg)
5829#endif
5830#ifndef zig_has_f80
5831#define zig_has_f80 0
38245832#define zig_make_f80(fp, repr) repr
5833#ifndef zig_make_repr_f80
5834#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5835#endif
38255836#undef zig_make_special_f80
38265837#define zig_make_special_f80(sign, name, arg, repr) repr
38275838#undef zig_init_special_f80
38285839#define zig_init_special_f80(sign, name, arg, repr) repr
38295840#endif
38305841
3831#if defined(zig_gcc) && defined(zig_x86)
3832#define zig_f128_has_miscompilations 1
3833#else
3834#define zig_f128_has_miscompilations 0
3835#endif
3836
38375842#define zig_has_f128 1
3838#define zig_libc_name_f128(name) name##q
5843#define zig_libc_name_f128(name) name##f128
38395844#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
3840#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113
5845#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI
5846#undef zig_has_f128
5847#if zig_little_endian
5848typedef struct { uint64_t lo, hi; } zig_f128;
5849#else
5850typedef struct { uint64_t hi, lo; } zig_f128;
5851#endif
5852#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }
5853#define zig_lo_repr_f128(arg) (arg).lo
5854#define zig_hi_repr_f128(arg) (arg).hi
5855#elif FLT_MANT_DIG == 113
38415856typedef float zig_f128;
38425857#define zig_make_f128(fp, repr) fp##f
3843#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113
5858#elif DBL_MANT_DIG == 113
38445859typedef double zig_f128;
38455860#define zig_make_f128(fp, repr) fp
3846#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113
5861#elif LDBL_MANT_DIG == 113
38475862typedef long double zig_f128;
38485863#define zig_make_f128(fp, repr) fp##l
3849#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113
5864#elif FLT128_MANT_DIG == 113
38505865typedef _Float128 zig_f128;
38515866#define zig_make_f128(fp, repr) fp##f128
3852#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113
5867#elif FLT64X_MANT_DIG == 113
38535868typedef _Float64x zig_f128;
38545869#define zig_make_f128(fp, repr) fp##f64x
3855#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)
5870#elif defined(__SIZEOF_FLOAT128__)
38565871typedef __float128 zig_f128;
38575872#define zig_make_f128(fp, repr) fp##q
38585873#undef zig_make_special_f128
38595874#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
38605875#else
38615876#undef zig_has_f128
3862#define zig_has_f128 0
3863#undef zig_make_special_f128
3864#undef zig_init_special_f128
3865#if defined(zig_darwin) || defined(zig_aarch64)
3866typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;
3867zig_basic_operator(zig_v2u64, xor_v2u64, ^)
3868#define zig_repr_f128 v2u64
3869typedef zig_v2u64 zig_f128;
3870#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }
3871#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128
3872#define zig_make_f128(fp, repr) zig_make_f128_##repr
3873#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3874#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3875#else
3876#define zig_repr_f128 u128
5877#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC)
5878#if defined(zig_msvc) && !defined(__clang__)
5879#include <emmintrin.h>
5880typedef __m128i zig_f128;
5881#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } }
5882#define zig_lo_repr_f128(arg) (arg).m128i_u64[0]
5883#define zig_hi_repr_f128(arg) (arg).m128i_u64[1]
5884#else
5885typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128;
5886#define zig_init_repr_f128(hi, lo) { lo, hi }
5887#define zig_lo_repr_f128(arg) (arg)[0]
5888#define zig_hi_repr_f128(arg) (arg)[1]
5889#endif
5890#else
38775891typedef zig_u128 zig_f128;
5892#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo)
5893#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo)
5894#define zig_lo_repr_f128(arg) zig_lo_u128(arg)
5895#define zig_hi_repr_f128(arg) zig_hi_u128(arg)
5896#endif
5897#endif
5898#ifndef zig_has_f128
5899#define zig_has_f128 0
38785900#define zig_make_f128(fp, repr) repr
5901#ifndef zig_make_repr_f128
5902#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo)
5903#endif
5904#undef zig_make_special_f128
38795905#define zig_make_special_f128(sign, name, arg, repr) repr
5906#undef zig_init_special_f128
38805907#define zig_init_special_f128(sign, name, arg, repr) repr
38815908#endif
3882#endif
38835909
38845910#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
38855911/* Emulate msvc abi on a gnu compiler */
......@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;
38925918typedef long double zig_c_longdouble;
38935919#endif
38945920
3895#define zig_bitCast_float(Type, ReprType) \
3896 static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \
3897 zig_##Type result; \
3898 memcpy(&result, &repr, sizeof(result)); \
3899 return result; \
5921#if __AVR__
5922typedef signed char zig_FloatCompareResult;
5923#elif defined(zig_aarch64)
5924typedef signed int zig_FloatCompareResult;
5925#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__
5926typedef signed long zig_FloatCompareResult;
5927#else
5928typedef signed long long zig_FloatCompareResult;
5929#endif
5930
5931#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \
5932 static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \
5933 zig_f##w res; \
5934 memcpy(&res, &arg, sizeof(zig_f##w)); \
5935 return res; \
5936 } \
5937 static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \
5938 zig_f##w res; \
5939 memcpy(&res, &arg, sizeof(zig_f##w)); \
5940 return res; \
5941 } \
5942 static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \
5943 UnsignedReprType res; \
5944 memcpy(&res, &arg, sizeof(zig_f##w)); \
5945 return zig_u##iw##_truncate_u##iw(res, w); \
5946 } \
5947 static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \
5948 SignedReprType res; \
5949 memcpy(&res, &arg, sizeof(zig_f##w)); \
5950 return zig_i##iw##_truncate_i##iw(res, w); \
39005951 }
3901zig_bitCast_float(f16, uint16_t)
3902zig_bitCast_float(f32, uint32_t)
3903zig_bitCast_float(f64, uint64_t)
3904zig_bitCast_float(f80, zig_u128)
3905zig_bitCast_float(f128, zig_u128)
5952zig_bitCast_float(16, 16, uint16_t, int16_t)
5953zig_bitCast_float(32, 32, uint32_t, int32_t)
5954zig_bitCast_float(64, 64, uint64_t, int64_t)
5955#if zig_has_f80
5956zig_bitCast_float(80, 128, zig_u128, zig_i128)
5957#else
5958static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) {
5959 return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg));
5960}
5961static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) {
5962 return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg));
5963}
5964static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) {
5965 return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5966}
5967static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) {
5968 return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5969}
5970#endif
5971static inline zig_f80 zig_f80_bitCast_big(const void *arg) {
5972 return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80)));
5973}
5974static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) {
5975 if (res_is_signed) {
5976 zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits);
5977 } else {
5978 zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits);
5979 }
5980}
5981#if zig_has_f128
5982zig_bitCast_float(128, 128, zig_u128, zig_i128)
5983#else
5984static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) {
5985 return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg));
5986}
5987static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) {
5988 return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg));
5989}
5990static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) {
5991 return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5992}
5993static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) {
5994 return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5995}
5996#endif
39065997
3907#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \
3908 zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3909 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \
5998#define zig_convert_float_00(ResType, operation, ArgType, version) \
5999 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6000 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \
6001 return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6002 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg)
6003#define zig_convert_float_01(ResType, operation, ArgType, version) \
6004 zig_convert_float_00(ResType, operation, ArgType, version)
6005#define zig_convert_float_10(ResType, operation, ArgType, version) \
6006 zig_convert_float_00(ResType, operation, ArgType, version)
6007#define zig_convert_float_11(ResType, operation, ArgType, version) \
6008 return (ResType)arg
6009#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \
39106010 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
39116011 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
3912 ResType res; \
3913 ExternResType extern_res; \
3914 ExternArgType extern_arg; \
3915 memcpy(&extern_arg, &arg, sizeof(extern_arg)); \
3916 extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3917 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \
3918 memcpy(&res, &extern_res, sizeof(res)); \
3919 return extern_res; \
3920 }
3921zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)
3922zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)
3923zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
3924zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
3925zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)
3926zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
3927zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
3928zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)
3929zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
3930zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
3931zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)
3932zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)
3933zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)
3934zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2)
3935zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2)
3936zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2)
3937zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
3938zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)
3939
3940#ifdef __ARM_EABI__
3941
3942zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64);
3943static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); }
3944
3945zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32);
3946static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); }
3947
3948#else /* __ARM_EABI__ */
3949
3950zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
3951zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
3952
3953#endif /* __ARM_EABI__ */
3954
3955#define zig_float_negate_builtin_0(w, c, sb) \
3956 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
3957#define zig_float_negate_builtin_1(w, c, sb) -arg
3958#define zig_float_negate_builtin(w, c, sb) \
6012 zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \
6013 zig_has_##arg_when)(ResType, operation, ArgType, version); \
6014 }
6015
6016#define zig_convert_floats(SmallType, BigType) \
6017 zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \
6018 zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2)
6019zig_convert_floats(f16, f32)
6020zig_convert_floats(f16, f64)
6021zig_convert_floats(f16, f80)
6022zig_convert_floats(f16, f128)
6023zig_convert_floats(f32, f64)
6024zig_convert_floats(f32, f80)
6025zig_convert_floats(f32, f128)
6026zig_convert_floats(f64, f80)
6027zig_convert_floats(f64, f128)
6028zig_convert_floats(f80, f128)
6029
6030#define zig_float_negate_builtin_0(w, sb) \
6031 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb))
6032#define zig_float_negate_builtin_1(w, sb) -arg
6033#define zig_float_negate_builtin(w, sb) \
39596034 static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \
3960 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \
6035 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \
39616036 }
3962zig_float_negate_builtin(16, , UINT16_C(1) << 15 )
3963zig_float_negate_builtin(32, , UINT32_C(1) << 31 )
3964zig_float_negate_builtin(64, , UINT64_C(1) << 63 )
3965zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))
3966zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
6037zig_float_negate_builtin(16, UINT16_C(1) << 15)
6038zig_float_negate_builtin(32, UINT32_C(1) << 31)
6039zig_float_negate_builtin(64, UINT64_C(1) << 63)
6040
6041#undef zig_float_negate_builtin_0
6042#define zig_float_negate_builtin_0(w, sb) \
6043 zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb))
6044zig_float_negate_builtin(80, UINT16_C(1) << 15)
6045
6046#undef zig_float_negate_builtin_0
6047#define zig_float_negate_builtin_0(w, sb) \
6048 zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg))
6049zig_float_negate_builtin(128, UINT64_C(1) << 63)
39676050
39686051#define zig_float_less_builtin_0(Type, operation) \
3969 zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
6052 zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \
39706053 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
39716054 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
3972 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
6055 return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
39736056 }
39746057#define zig_float_less_builtin_1(Type, operation) \
39756058 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
......@@ -3994,13 +6077,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
39946077 return lhs operator rhs; \
39956078 }
39966079
6080#define zig_float_builtins(w) \
6081 zig_common_float_builtins(w) \
6082 zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \
6083 zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, )
39976084#define zig_common_float_builtins(w) \
3998 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
3999 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
4000 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \
4001 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \
4002 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
4003 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
6085 zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \
6086 zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \
6087 zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \
6088 zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \
6089 zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \
6090 zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \
6091 zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \
6092 zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \
6093 zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \
6094 zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \
6095\
6096 static inline void zig_expand_concat(zig_expand_concat(zig_fix, \
6097 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6098 zig_extern void zig_expand_concat(zig_expand_concat(__fix, \
6099 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6100 zig_expand_concat(zig_expand_concat(__fix, \
6101 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6102 } \
6103\
6104 static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \
6105 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6106 zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \
6107 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6108 zig_expand_concat(zig_expand_concat(__fixuns, \
6109 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6110 } \
6111\
6112 static inline zig_f##w zig_expand_concat(zig_floatei, \
6113 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6114 zig_extern zig_f##w zig_expand_concat(__floatei, \
6115 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6116 return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6117 } \
6118\
6119 static inline zig_f##w zig_expand_concat(zig_floatunei, \
6120 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6121 zig_extern zig_f##w zig_expand_concat(__floatunei, \
6122 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6123 return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6124 } \
6125\
40046126 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
40056127 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
40066128 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \
......@@ -4031,82 +6153,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
40316153 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \
40326154 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \
40336155\
4034 static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
6156 static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
40356157 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
40366158 } \
40376159\
4038 static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
6160 static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \
40396161 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
40406162 } \
40416163\
4042 static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \
6164 static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \
40436165 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \
40446166 } \
40456167\
40466168 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
4047 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
6169 return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \
40486170 }
4049zig_common_float_builtins(16)
4050zig_common_float_builtins(32)
4051zig_common_float_builtins(64)
4052zig_common_float_builtins(80)
4053zig_common_float_builtins(128)
4054
4055#define zig_float_builtins(w) \
4056 zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
4057 zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
4058 zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
4059 zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
4060 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
4061 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, )
40626171zig_float_builtins(16)
4063zig_float_builtins(80)
4064zig_float_builtins(128)
4065
4066#ifdef __ARM_EABI__
4067
4068zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32);
4069static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); }
4070
4071zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32);
4072static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); }
4073
4074zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32);
4075static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); }
4076
4077zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t);
4078static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); }
4079
4080zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t);
4081static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); }
4082
4083zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t);
4084static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); }
4085
4086zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64);
4087static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); }
4088
4089zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64);
4090static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); }
4091
4092zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64);
4093static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); }
4094
4095zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t);
4096static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); }
4097
4098zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t);
4099static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); }
4100
4101zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t);
4102static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); }
4103
4104#else /* __ARM_EABI__ */
4105
41066172zig_float_builtins(32)
41076173zig_float_builtins(64)
4108
4109#endif /* __ARM_EABI__ */
6174zig_float_builtins(80)
6175#if defined(zig_x86_32)
6176zig_common_float_builtins(128)
6177static inline zig_f128 zig_floattitf(zig_i128 arg) {
6178 extern zig_f128 __floattitf(zig_f128 arg);
6179 return __floattitf(zig_f128_bitCast_i128(arg));
6180}
6181static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6182 extern zig_f128 __floatuntitf(zig_f128 arg);
6183 return __floatuntitf(zig_f128_bitCast_u128(arg));
6184}
6185#elif defined(zig_x86_64) && defined(zig_windows)
6186zig_common_float_builtins(128)
6187static inline zig_f128 zig_floattitf(zig_i128 arg) {
6188 extern zig_f128 __floattitf(zig_i128 arg);
6189 return __floattitf(arg);
6190}
6191static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6192 extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi);
6193 return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg));
6194}
6195#else
6196zig_float_builtins(128)
6197#endif
41106198
41116199/* ============================ Atomics Support ============================= */
41126200
......@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;
44106498 } \
44116499 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
44126500 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
4413 } \
6501 } \
44146502 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
44156503 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44166504 } \
44176505 static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \
4418 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6506 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44196507 _ReadWriteBarrier(); \
4420 return val; \
6508 return value; \
44216509 } \
44226510 static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \
4423 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6511 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44246512 _ReadWriteBarrier(); \
4425 return val; \
6513 return value; \
44266514 }
44276515
44286516zig_msvc_atomics( u8, uint8_t, char, 8, 8)
......@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
44656553 zig_##Type result; \
44666554 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44676555 _ReadWriteBarrier(); \
4468 memcpy(&result, &initial, sizeof(result)); \
6556 memcpy(&result, &initial, sizeof(result)); \
44696557 return result; \
44706558 } \
44716559 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
44726560 zig_##Type result; \
44736561 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44746562 _ReadWriteBarrier(); \
4475 memcpy(&result, &initial, sizeof(result)); \
6563 memcpy(&result, &initial, sizeof(result)); \
44766564 return result; \
44776565 }
44786566
......@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat
45026590}
45036591
45046592static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {
4505 void* val = (void*)__iso_volatile_load32(obj);
6593 void* value = (void*)__iso_volatile_load32(obj);
45066594 _ReadWriteBarrier();
4507 return val;
6595 return value;
45086596}
45096597
45106598static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) {
......@@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat
45326620}
45336621
45346622static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {
4535 void* val = (void*)__iso_volatile_load64(obj);
6623 void* value = (void*)__iso_volatile_load64(obj);
45366624 _ReadWriteBarrier();
4537 return val;
6625 return value;
45386626}
45396627
45406628static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {
src/Compilation.zig+3
......@@ -2134,6 +2134,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
21342134 comp.config.any_fuzz = any_fuzz;
21352135
21362136 if (opt_zcu) |zcu| {
2137 // Finish initializing the `zcu` after the fields on `comp` have been initialized.
2138 zcu.initAfterCompilation();
2139
21372140 // Populate `zcu.module_roots`.
21382141 const active = zcu.acquire();
21392142 defer active.release();
src/InternPool.zig+27-27
......@@ -4193,7 +4193,7 @@ pub const Index = enum(u32) {
41934193 };
41944194 }
41954195
4196 /// This function is used in the debugger pretty formatters in tools/ to fetch the
4196 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the
41974197 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
41984198 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
41994199 const DataIsIndex = struct { data: Index };
......@@ -4219,26 +4219,17 @@ pub const Index = enum(u32) {
42194219 type_inferred_error_set: DataIsIndex,
42204220 simple_type: void,
42214221 type_function: struct {
4222 const @"data.flags.has_comptime_bits" = opaque {};
4223 const @"data.flags.has_noalias_bits" = opaque {};
4224 const @"data.flags.cc.extraLen()" = opaque {};
42254222 const @"data.params_len" = opaque {};
42264223 data: *Tag.TypeFunction,
4227 @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits",
4228 @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits",
4229 @"trailing.cc_bits.len": *@"data.flags.cc.extraLen()",
42304224 @"trailing.param_types.len": *@"data.params_len",
4231 trailing: struct { comptime_bits: []u32, noalias_bits: []u32, cc_bits: []u32, param_types: []Index },
4225 trailing: struct { param_types: []Index },
42324226 },
42334227 type_tuple: struct {
42344228 const @"data.fields_len" = opaque {};
42354229 data: *TypeTuple,
42364230 @"trailing.types.len": *@"data.fields_len",
42374231 @"trailing.values.len": *@"data.fields_len",
4238 trailing: struct {
4239 types: []Index,
4240 values: []Index,
4241 },
4232 trailing: struct { types: []Index, values: []Index },
42424233 },
42434234
42444235 type_struct: struct { data: *Tag.TypeStruct },
......@@ -4350,7 +4341,7 @@ pub const Index = enum(u32) {
43504341 const encoding = @field(Tag.encodings, tag_name);
43514342 if (@hasField(@TypeOf(encoding), "trailing")) {
43524343 const trailing_info = @typeInfo(encoding.trailing).@"struct";
4353 for (trailing_info.field_names, trailing_info.field_types) |field_name, field_type| {
4344 for (trailing_info.field_names, trailing_info.field_types) |trailing_field_name, trailing_field_type| {
43544345 struct {
43554346 fn checkConfig(name: []const u8) void {
43564347 if (!@hasField(@TypeOf(encoding.config), name)) @compileError("missing field: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ ".config.@\"" ++ name ++ "\"");
......@@ -4359,22 +4350,30 @@ pub const Index = enum(u32) {
43594350 }
43604351 fn checkField(name: []const u8, Type: type) void {
43614352 switch (@typeInfo(Type)) {
4362 .int => {},
4363 .@"enum" => {},
4364 .@"struct" => |info| assert(info.layout == .@"packed"),
4353 .int, .@"enum" => return,
4354 .@"struct" => |info| switch (info.layout) {
4355 .auto => unreachable,
4356 .@"extern" => {
4357 for (info.field_names, info.field_types) |field_name, field_type| checkField(name ++ "." ++ field_name, field_type);
4358 return;
4359 },
4360 .@"packed" => return,
4361 },
43654362 .optional => |info| {
43664363 checkConfig(name ++ ".?");
43674364 checkField(name ++ ".?", info.child);
4365 return;
43684366 },
4369 .pointer => |info| {
4370 assert(info.size == .slice);
4367 .pointer => |info| if (info.size == .slice) {
43714368 checkConfig(name ++ ".len");
43724369 checkField(name ++ "[0]", info.child);
4370 return;
43734371 },
4374 else => @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)),
4372 else => {},
43754373 }
4374 @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type));
43764375 }
4377 }.checkField("trailing." ++ field_name, field_type);
4376 }.checkField("trailing." ++ trailing_field_name, trailing_field_type);
43784377 }
43794378 }
43804379 },
......@@ -5186,17 +5185,18 @@ pub const Tag = enum(u8) {
51865185 .trailing = struct {
51875186 param_comptime_bits: ?[]u32,
51885187 param_noalias_bits: ?[]u32,
5189 param_cc_bits: ?[]u32,
5190 param_type: []Index,
5188 spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 },
5189 spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 },
5190 param_types: []Index,
51915191 },
51925192 .config = .{
51935193 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits",
51945194 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
51955195 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
51965196 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
5197 .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0",
5198 .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()",
5199 .@"trailing.param_type.len" = .@"payload.params_len",
5197 .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task",
5198 .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh",
5199 .@"trailing.param_types.len" = .@"payload.params_len",
52005200 },
52015201 },
52025202
......@@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) {
52255225 .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults",
52265226 .@"trailing.field_defaults.?.len" = .@"payload.fields_len",
52275227 .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns",
5228 .@"trailing.field_aligns.?.len" = .@"payload.fields_len",
5228 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4",
52295229 .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields",
52305230 .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32",
52315231 .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto",
......@@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) {
52545254 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
52555255 .@"trailing.field_types.len" = .@"payload.fields_len",
52565256 .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns",
5257 .@"trailing.field_aligns.?.len" = .@"payload.fields_len",
5257 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4",
52585258 },
52595259 },
52605260 .type_union_packed_auto = union_packed_encoding,
src/Sema.zig+6-5
......@@ -8501,6 +8501,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta
85018501 .x86_64_win,
85028502 .x86_sysv,
85038503 .x86_win,
8504 .x86_mingw,
85048505 .aarch64_aapcs,
85058506 .aarch64_aapcs_darwin,
85068507 .aarch64_aapcs_win,
......@@ -25675,7 +25676,6 @@ pub fn explainWhyTypeIsNotExtern(
2567525676
2567625677 .@"opaque",
2567725678 .bool,
25678 .float,
2567925679 .@"anyframe",
2568025680 => unreachable, // these *are* allowed
2568125681
......@@ -25684,6 +25684,7 @@ pub fn explainWhyTypeIsNotExtern(
2568425684 try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{});
2568525685 },
2568625686
25687 .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}),
2568725688 .pointer => if (ty.isSlice(zcu)) {
2568825689 try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
2568925690 } else {
......@@ -29657,7 +29658,7 @@ fn coerceVarArgParam(
2965729658 .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
2965829659 .float => float: {
2965929660 const target = zcu.getTarget();
29660 const double_bits = target.cTypeBitSize(.double);
29661 const double_bits = target.cTypeBitSize(.double) orelse break :float inst;
2966129662 const inst_bits = uncasted_ty.floatBits(target);
2966229663 if (inst_bits >= double_bits) break :float inst;
2966329664 switch (double_bits) {
......@@ -29673,21 +29674,21 @@ fn coerceVarArgParam(
2967329674 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
2967429675 .signed => .int,
2967529676 .unsigned => .uint,
29676 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29677 }) orelse break :int inst) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
2967729678 .signed => .c_int,
2967829679 .unsigned => .c_uint,
2967929680 }, inst, inst_src);
2968029681 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
2968129682 .signed => .long,
2968229683 .unsigned => .ulong,
29683 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29684 }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
2968429685 .signed => .c_long,
2968529686 .unsigned => .c_ulong,
2968629687 }, inst, inst_src);
2968729688 if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) {
2968829689 .signed => .longlong,
2968929690 .unsigned => .ulonglong,
29690 })) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
29691 }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) {
2969129692 .signed => .c_longlong,
2969229693 .unsigned => .c_ulonglong,
2969329694 }, inst, inst_src);
src/Sema/type_resolution.zig+1-1
......@@ -364,7 +364,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
364364 const a = struct_obj.field_aligns.get(ip)[field_idx];
365365 if (a != .none) break :a a;
366366 }
367 break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu);
367 break :a field_ty.abiAlignment(zcu);
368368 };
369369 align_out.* = field_align;
370370 if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) {
src/Type.zig+107-86
......@@ -957,12 +957,27 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
957957 if (vector_type.len == 0) return .@"1";
958958 switch (zcu.comp.getZigBackend()) {
959959 else => {
960 const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu));
960 const elem_ty: Type = .fromInterned(vector_type.child);
961 switch (if (elem_ty.isRuntimeFloat())
962 std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target))
963 else
964 .hard) {
965 .hard => {},
966 .soft => return elem_ty.abiAlignment(zcu),
967 }
968 const elem_bits: u32 = @intCast(elem_ty.bitSize(zcu));
961969 if (elem_bits == 0) return .@"1";
962970 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
963 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));
971 const arch = target.cpu.arch;
972 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(
973 u32,
974 if (arch.isArm() or arch.isAARCH64() or arch == .s390x)
975 @min(bytes, target.stackAlignment())
976 else
977 bytes,
978 ));
964979 },
965 .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).defaultStructFieldAlignment(.auto, zcu),
980 .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu),
966981 .stage2_x86_64 => {
967982 if (vector_type.child == .bool_type) {
968983 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64";
......@@ -1018,19 +1033,33 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
10181033 .c_ulonglong => cTypeAlign(target, .ulonglong),
10191034 .c_longdouble => cTypeAlign(target, .longdouble),
10201035
1021 .f16 => .@"2",
1022 .f32 => if (target.os.tag == .opengl) .@"4" else cTypeAlign(target, .float),
1023 .f64 => if (target.os.tag == .opengl) .@"8" else switch (target.cTypeBitSize(.double)) {
1024 64 => cTypeAlign(target, .double),
1025 else => .@"8",
1026 },
1027 .f80 => switch (target.cTypeBitSize(.longdouble)) {
1028 80 => cTypeAlign(target, .longdouble),
1029 else => Type.u80.abiAlignment(zcu),
1030 },
1031 .f128 => switch (target.cTypeBitSize(.longdouble)) {
1032 128 => cTypeAlign(target, .longdouble),
1033 else => .@"16",
1036 .f16 => .fromByteUnits(std.zig.target.intAlignment(target, 16)), // repr: u16
1037 .f32 => if (target.cTypeBitSize(.float) == 32)
1038 cTypeAlign(target, .float) // abi: c_float,
1039 else
1040 .fromByteUnits(std.zig.target.intAlignment(target, 32)), // repr: u32,
1041 .f64 => if (target.cTypeBitSize(.double) == 64)
1042 cTypeAlign(target, .double) // abi: c_double,
1043 else
1044 .fromByteUnits(std.zig.target.intAlignment(target, 64)), // repr: u64,
1045 .f80 => if (target.cTypeBitSize(.longdouble) == 80)
1046 cTypeAlign(target, .longdouble) // abi: c_longdouble,
1047 else
1048 .fromByteUnits(switch (std.zig.target.compilerRtFloatAbi(target, 80)) {
1049 .hard => std.zig.target.intAlignment(target, 80), // repr: u80,
1050 .soft => @max(
1051 std.zig.target.intAlignment(target, 64), // mantissa: u64,
1052 std.zig.target.intAlignment(target, 16), // exponent: u16,
1053 ),
1054 }),
1055 .f128 => if (target.cTypeBitSize(.longdouble) == 128)
1056 cTypeAlign(target, .longdouble) // abi: c_longdouble,
1057 else switch (std.zig.target.compilerRtFloatAbi(target, 128)) {
1058 .hard => if (target.cpu.arch.isX86())
1059 .@"16" // abi: c___float128,
1060 else
1061 .fromByteUnits(std.zig.target.intAlignment(target, 128)), // repr: u128,
1062 .soft => .fromByteUnits(std.zig.target.intAlignment(target, 64)), // lo: u64, hi: u64,
10341063 },
10351064
10361065 .generic_poison => unreachable,
......@@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
11111140 .vector_type => |vec| {
11121141 const elem_ty: Type = .fromInterned(vec.child);
11131142 const bytes = switch (zcu.comp.getZigBackend()) {
1114 else => @divCeil(vec.len * elem_ty.bitSize(zcu), 8),
1143 else => switch (if (elem_ty.isRuntimeFloat())
1144 std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target))
1145 else
1146 .hard) {
1147 .hard => @divCeil(vec.len * elem_ty.bitSize(zcu), 8),
1148 .soft => vec.len * elem_ty.abiSize(zcu),
1149 },
11151150 .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu),
11161151 .stage2_x86_64 => switch (elem_ty.toIntern()) {
11171152 .bool_type => @divCeil(vec.len, 8),
......@@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
11671202 .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu),
11681203 .usize, .isize => ptrAbiSize(target),
11691204
1170 .c_char => target.cTypeByteSize(.char),
1171 .c_short => target.cTypeByteSize(.short),
1172 .c_ushort => target.cTypeByteSize(.ushort),
1173 .c_int => target.cTypeByteSize(.int),
1174 .c_uint => target.cTypeByteSize(.uint),
1175 .c_long => target.cTypeByteSize(.long),
1176 .c_ulong => target.cTypeByteSize(.ulong),
1177 .c_longlong => target.cTypeByteSize(.longlong),
1178 .c_ulonglong => target.cTypeByteSize(.ulonglong),
1179 .c_longdouble => target.cTypeByteSize(.longdouble),
1180
1181 .f16 => 2,
1182 .f32 => 4,
1183 .f64 => 8,
1184 .f80 => switch (target.cTypeBitSize(.longdouble)) {
1185 80 => target.cTypeByteSize(.longdouble),
1186 else => Type.u80.abiSize(zcu),
1205 .c_char => target.cTypeByteSize(.char).?,
1206 .c_short => target.cTypeByteSize(.short).?,
1207 .c_ushort => target.cTypeByteSize(.ushort).?,
1208 .c_int => target.cTypeByteSize(.int).?,
1209 .c_uint => target.cTypeByteSize(.uint).?,
1210 .c_long => target.cTypeByteSize(.long).?,
1211 .c_ulong => target.cTypeByteSize(.ulong).?,
1212 .c_longlong => target.cTypeByteSize(.longlong).?,
1213 .c_ulonglong => target.cTypeByteSize(.ulonglong).?,
1214 .c_longdouble => target.cTypeByteSize(.longdouble).?,
1215
1216 .f16 => std.zig.target.intByteSize(target, 16), // repr: u16
1217 .f32 => if (target.cTypeBitSize(.float) == 32)
1218 target.cTypeByteSize(.float).? // abi: c_float,
1219 else
1220 std.zig.target.intByteSize(target, 32), // repr: u32,
1221 .f64 => if (target.cTypeBitSize(.double) == 64)
1222 target.cTypeByteSize(.double).? // abi: c_double,
1223 else
1224 std.zig.target.intByteSize(target, 64), // repr: u64,
1225 .f80 => if (target.cTypeBitSize(.longdouble) == 80)
1226 target.cTypeByteSize(.longdouble).? // abi: c_longdouble,
1227 else switch (std.zig.target.compilerRtFloatAbi(target, 80)) {
1228 .hard => std.zig.target.intByteSize(target, 80), // repr: u80,
1229 .soft => ty.abiAlignment(zcu).forward(
1230 std.zig.target.intByteSize(target, 64) + // mantissa: u64,
1231 std.zig.target.intByteSize(target, 16), // exponent: u16
1232 ),
1233 },
1234 .f128 => if (target.cTypeBitSize(.longdouble) == 128)
1235 target.cTypeByteSize(.longdouble).? // abi: c_longdouble,
1236 else switch (std.zig.target.compilerRtFloatAbi(target, 128)) {
1237 .hard => if (target.cpu.arch.isX86())
1238 16 // abi: c___float128,
1239 else
1240 std.zig.target.intByteSize(target, 128), // repr: u128,
1241 .soft => std.zig.target.intByteSize(target, 64) * 2, // lo: u64, hi: u64,
11871242 },
1188 .f128 => 16,
11891243
11901244 .anyopaque => unreachable,
11911245 .generic_poison => unreachable,
......@@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool {
17331787/// Returns true if and only if the type is a fixed-width, signed integer.
17341788pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {
17351789 return switch (ty.toIntern()) {
1736 .c_char_type => zcu.getTarget().cCharSignedness() == .signed,
1790 .c_char_type => zcu.getTarget().cCharSignedness().? == .signed,
17371791 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
17381792 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
17391793 .int_type => |int_type| int_type.signedness == .signed,
......@@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool {
17451799/// Returns true if and only if the type is a fixed-width, unsigned integer.
17461800pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool {
17471801 return switch (ty.toIntern()) {
1748 .c_char_type => zcu.getTarget().cCharSignedness() == .unsigned,
1802 .c_char_type => zcu.getTarget().cCharSignedness().? == .unsigned,
17491803 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
17501804 else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
17511805 .int_type => |int_type| int_type.signedness == .unsigned,
......@@ -1776,15 +1830,15 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
17761830 },
17771831 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
17781832 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
1779 .c_char_type => return .{ .signedness = zcu.getTarget().cCharSignedness(), .bits = target.cTypeBitSize(.char) },
1780 .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short) },
1781 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort) },
1782 .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int) },
1783 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint) },
1784 .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long) },
1785 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong) },
1786 .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong) },
1787 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) },
1833 .c_char_type => return .{ .signedness = target.cCharSignedness().?, .bits = target.cTypeBitSize(.char).? },
1834 .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short).? },
1835 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort).? },
1836 .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int).? },
1837 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint).? },
1838 .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long).? },
1839 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong).? },
1840 .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong).? },
1841 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong).? },
17881842 else => switch (ip.indexToKey(ty.toIntern())) {
17891843 .int_type => |int_type| return int_type,
17901844 .struct_type => {
......@@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 {
18821936 .f64_type => 64,
18831937 .f80_type => 80,
18841938 .f128_type, .comptime_float_type => 128,
1885 .c_longdouble_type => target.cTypeBitSize(.longdouble),
1939 .c_longdouble_type => target.cTypeBitSize(.longdouble).?,
18861940
18871941 else => unreachable,
18881942 };
......@@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool {
21472201 return ty.zigTypeTag(zcu) == .vector;
21482202}
21492203
2150/// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len.
2151pub fn totalVectorBits(ty: Type, zcu: *Zcu) u64 {
2152 if (!ty.isVector(zcu)) return 0;
2153 const v = zcu.intern_pool.indexToKey(ty.toIntern()).vector_type;
2154 return v.len * Type.fromInterned(v.child).bitSize(zcu);
2155}
2156
21572204pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool {
21582205 return switch (ty.zigTypeTag(zcu)) {
21592206 .array, .vector => true,
......@@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment
24162463 };
24172464}
24182465
2419/// Returns the alignment a struct field of type `field_ty` will be given if no alignment is
2420/// explicitly specified. However, in an `extern struct`, a higher alignment may be available due
2421/// to the struct's full layout (i.e. a field might coincidentally be more aligned).
2422///
2423/// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`.
2424pub fn defaultStructFieldAlignment(
2425 field_ty: Type,
2426 layout: std.lang.Type.ContainerLayout,
2427 zcu: *const Zcu,
2428) Alignment {
2429 const overalign_big_int = switch (layout) {
2430 .@"packed" => unreachable,
2431 .auto => zcu.getTarget().ofmt == .c,
2432 .@"extern" => true,
2433 };
2434 const abi_align = field_ty.abiAlignment(zcu);
2435 assert(abi_align != .none);
2436 // We check for anything over 64 here, because the C backend will lower e.g. u64 to a 128-bit
2437 // integer, which has 16-byte alignment.
2438 if (overalign_big_int and
2439 ((field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits > 64) or
2440 (field_ty.toIntern() == .f80_type and zcu.getTarget().cTypeBitSize(.longdouble) != 80)))
2441 {
2442 return abi_align.maxStrict(if (zcu.getTarget().cpu.arch == .s390x) .@"8" else .@"16");
2443 }
2444 return abi_align;
2445}
2446
24472466pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value {
24482467 const ip = &zcu.intern_pool;
24492468 switch (ip.indexToKey(ty.toIntern())) {
......@@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
29612980 }
29622981 const actual_field_align = switch (field_align) {
29632982 .none => switch (ip.indexToKey(aggregate_ty.toIntern())) {
2964 .tuple_type, .union_type => field_ty.abiAlignment(zcu),
2965 .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu),
2983 .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu),
29662984 .ptr_type => Type.usize.abiAlignment(zcu),
29672985 else => unreachable,
29682986 },
......@@ -3122,7 +3140,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
31223140
31233141 .@"opaque",
31243142 .bool,
3125 .float,
31263143 .@"anyframe",
31273144 => true,
31283145
......@@ -3144,6 +3161,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
31443161 24, 48 => zcu.getTarget().cpu.arch == .ez80,
31453162 else => false,
31463163 },
3164 .float => switch (ty.floatBits(zcu.getTarget())) {
3165 else => true,
3166 80 => zcu.getTarget().cTypeBitSize(.longdouble) == 80,
3167 },
31473168 .@"fn" => {
31483169 if (position != .other) return false;
31493170 return validateExternCallconv(ty.fnCallingConvention(zcu));
......@@ -3600,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 {
36003621pub const packed_struct_layout_version = 2;
36013622
36023623fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment {
3603 return Alignment.fromByteUnits(target.cTypeAlignment(c_type));
3624 return .fromByteUnits(target.cTypeAlignment(c_type).?);
36043625}
src/Value.zig+1-6
......@@ -611,12 +611,7 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T {
611611 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
612612 .int => |int| switch (int.storage) {
613613 .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0],
614 inline .u64, .i64 => |x| {
615 if (T == f80) {
616 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
617 }
618 return @floatFromInt(x);
619 },
614 inline .u64, .i64 => |x| @floatFromInt(x),
620615 },
621616 .float => |float| switch (float.storage) {
622617 inline else => |x| @floatCast(x),
src/Zcu.zig+13-24
......@@ -2825,6 +2825,11 @@ pub const CompileError = error{
28252825
28262826pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void {
28272827 try zcu.intern_pool.init(gpa, io, thread_count);
2828}
2829
2830/// It is valid to not call this function before `deinit` in error paths.
2831/// Requires the fields on `zcu.comp` to already be initialized.
2832pub fn initAfterCompilation(zcu: *Zcu) void {
28282833 zcu.initTracyPlots();
28292834}
28302835
......@@ -4612,43 +4617,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46124617 .m68k_rtd,
46134618 .m68k_interrupt,
46144619 .msp430_interrupt,
4615 => |opts| opts.incoming_stack_alignment == null,
4616
46174620 .arm_aapcs_vfp,
4618 => |opts| opts.incoming_stack_alignment == null,
4619
46204621 .arc_interrupt,
4621 => |opts| opts.incoming_stack_alignment == null,
4622
46234622 .arm_interrupt,
4624 => |opts| opts.incoming_stack_alignment == null,
4625
46264623 .microblaze_interrupt,
4627 => |opts| opts.incoming_stack_alignment == null,
4628
46294624 .mips_interrupt,
46304625 .mips64_interrupt,
4631 => |opts| opts.incoming_stack_alignment == null,
4632
46334626 .riscv32_interrupt,
46344627 .riscv64_interrupt,
4635 => |opts| opts.incoming_stack_alignment == null,
4636
46374628 .sh_interrupt,
4638 => |opts| opts.incoming_stack_alignment == null,
4629 .avr_interrupt,
4630 .avr_signal,
4631 .ez80_tiflags,
4632 .naked,
4633 => true, // incoming stack alignment supported
46394634
46404635 .x86_sysv,
46414636 .x86_win,
4637 .x86_mingw,
46424638 .x86_stdcall,
4643 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
4644
4645 .avr_interrupt,
4646 .avr_signal,
4647 => true,
4648
4649 .ez80_tiflags => true,
4650
4651 .naked => true,
4639 => |opts| opts.register_params == 0, // incoming stack alignment supported
46524640
46534641 else => false,
46544642 };
......@@ -4673,6 +4661,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46734661 .stage2_x86 => switch (cc) {
46744662 .x86_sysv,
46754663 .x86_win,
4664 .x86_mingw,
46764665 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
46774666 .naked => true,
46784667 else => false,
src/codegen.zig+195
......@@ -1124,6 +1124,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu:
11241124 };
11251125}
11261126
1127pub const FlattenedItem = struct { offset: u64, type: ?Type };
1128pub fn flattenType(items_buf: []FlattenedItem, ty: Type, zcu: *Zcu, opts: struct {
1129 offset: u64 = 0,
1130 allow_arrays: bool = true,
1131 fn increaseOffset(opts: @This(), offset: u64) @This() {
1132 return .{
1133 .offset = opts.offset + offset,
1134 .allow_arrays = opts.allow_arrays,
1135 };
1136 }
1137}) ?[]FlattenedItem {
1138 const ip = &zcu.intern_pool;
1139 switch (ip.indexToKey(ty.toIntern())) {
1140 .int_type => |int_type| {
1141 if (int_type.bits == 0) return items_buf[0..0];
1142 if (items_buf.len < 1) return null;
1143 const items = items_buf[0..1];
1144 items.* = .{.{ .offset = opts.offset, .type = ty }};
1145 return items;
1146 },
1147 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1148 .one, .many, .c => {
1149 if (items_buf.len < 1) return null;
1150 const items = items_buf[0..1];
1151 items.* = .{.{ .offset = opts.offset, .type = ty }};
1152 return items;
1153 },
1154 .slice => {
1155 if (items_buf.len < 2) return null;
1156 const items = items_buf[0..2];
1157 const ptr_field_ty = ty.slicePtrFieldType(zcu);
1158 items.* = .{
1159 .{ .offset = opts.offset, .type = ptr_field_ty },
1160 .{ .offset = opts.offset + ptr_field_ty.abiSize(zcu), .type = .usize },
1161 };
1162 return items;
1163 },
1164 },
1165 .array_type => |array_type| {
1166 const len = array_type.lenIncludingSentinel();
1167 if (len == 0) return items_buf[0..0];
1168 const elem_ty: Type = .fromInterned(array_type.child);
1169 const elem_items = flattenType(items_buf, elem_ty, zcu, opts) orelse return null;
1170 if (elem_items.len == 0) return items_buf[0..0];
1171 if (!opts.allow_arrays) return null;
1172 const items_len, const items_overflow = @mulWithOverflow(elem_items.len, len);
1173 if (items_overflow != 0 or items_buf.len < items_len) return null;
1174 var items_index = elem_items.len;
1175 const elem_size = elem_ty.abiSize(zcu);
1176 var elem_offset: u64 = elem_size;
1177 while (items_index != items_len) : ({
1178 items_index += elem_items.len;
1179 elem_offset += elem_size;
1180 }) for (items_buf[items_index..][0..elem_items.len], elem_items) |*item, elem_item| {
1181 item.* = .{ .offset = elem_offset + elem_item.offset, .type = elem_item.type };
1182 };
1183 return items_buf[0..@intCast(items_len)];
1184 },
1185 .vector_type => |vector_type| {
1186 if (vector_type.len == 0) return items_buf[0..0];
1187 if (items_buf.len < 1) return null;
1188 const items = items_buf[0..1];
1189 items.* = .{.{ .offset = opts.offset, .type = ty }};
1190 return items;
1191 },
1192 .opt_type, .error_union_type => return null,
1193 .simple_type => |simple_type| switch (simple_type) {
1194 .f16,
1195 .f32,
1196 .f64,
1197 .f80,
1198 .f128,
1199 .usize,
1200 .isize,
1201 .c_char,
1202 .c_short,
1203 .c_ushort,
1204 .c_int,
1205 .c_uint,
1206 .c_long,
1207 .c_ulong,
1208 .c_longlong,
1209 .c_ulonglong,
1210 .c_longdouble,
1211 .bool,
1212 .anyerror,
1213 => {
1214 if (items_buf.len < 1) return null;
1215 const items = items_buf[0..1];
1216 items.* = .{.{ .offset = opts.offset, .type = ty }};
1217 return items;
1218 },
1219 .anyopaque, .noreturn => return null,
1220 .void,
1221 .type,
1222 .comptime_int,
1223 .comptime_float,
1224 .null,
1225 .undefined,
1226 .enum_literal,
1227 => return items_buf[0..0],
1228 .adhoc_inferred_error_set, .generic_poison => unreachable,
1229 },
1230 .struct_type => {
1231 const loaded_struct = ip.loadStructType(ty.toIntern());
1232 switch (loaded_struct.layout) {
1233 .auto, .@"extern" => {},
1234 .@"packed" => return flattenType(items_buf, .fromInterned(
1235 loaded_struct.packed_backing_int_type,
1236 ), zcu, opts),
1237 }
1238 var items_len: usize = 0;
1239 var offset: u64 = 0;
1240 var field_it = loaded_struct.iterateRuntimeOrder(ip);
1241 while (field_it.next()) |field_index| {
1242 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1243 const field_offset = loaded_struct.field_offsets.get(ip)[field_index];
1244 if (field_offset - offset > 0 and
1245 (items_len == 0 or items_buf[items_len - 1].type != null))
1246 {
1247 if (items_len == items_buf.len) return null;
1248 items_buf[items_len] = .{ .offset = offset, .type = null };
1249 items_len += 1;
1250 }
1251 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset(
1252 field_offset,
1253 )) orelse return null).len;
1254 offset = field_offset + field_ty.abiSize(zcu);
1255 }
1256 if (ty.abiSize(zcu) - offset > 0 and
1257 (items_len == 0 or items_buf[items_len - 1].type != null))
1258 {
1259 if (items_len == items_buf.len) return null;
1260 items_buf[items_len] = .{ .offset = offset, .type = null };
1261 items_len += 1;
1262 }
1263 return items_buf[0..items_len];
1264 },
1265 .tuple_type => |tuple_type| {
1266 if (items_buf.len < tuple_type.types.len) return null;
1267 var items_len: usize = 0;
1268 var offset: u64 = 0;
1269 for (tuple_type.types.get(ip)) |field_ty_ip| {
1270 const field_ty: Type = .fromInterned(field_ty_ip);
1271 offset = field_ty.abiAlignment(zcu).forward(offset);
1272 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset(
1273 offset,
1274 )) orelse return null).len;
1275 offset += field_ty.abiSize(zcu);
1276 }
1277 return items_buf[0..items_len];
1278 },
1279 .union_type => {
1280 const loaded_union = ip.loadUnionType(ty.toIntern());
1281 return switch (loaded_union.layout) {
1282 .auto, .@"extern" => return null,
1283 .@"packed" => return flattenType(items_buf, .fromInterned(
1284 loaded_union.packed_backing_int_type,
1285 ), zcu, opts),
1286 };
1287 },
1288 .opaque_type, .spirv_type, .func_type => return null,
1289 .enum_type => return flattenType(items_buf, .fromInterned(
1290 ip.loadEnumType(ty.toIntern()).int_tag_type,
1291 ), zcu, opts),
1292 .error_set_type, .inferred_error_set_type => {
1293 if (items_buf.len < 1) return null;
1294 const items = items_buf[0..1];
1295 items.* = .{.{ .offset = opts.offset, .type = ty }};
1296 return items;
1297 },
1298 .anyframe_type,
1299 // values, not types
1300 .undef,
1301 .simple_value,
1302 .@"extern",
1303 .func,
1304 .int,
1305 .err,
1306 .error_union,
1307 .enum_literal,
1308 .enum_tag,
1309 .float,
1310 .ptr,
1311 .slice,
1312 .opt,
1313 .aggregate,
1314 .un,
1315 .bitpack,
1316 // memoization, not types
1317 .memoized_call,
1318 => unreachable,
1319 }
1320}
1321
11271322test {
11281323 _ = aarch64;
11291324}
src/codegen/aarch64/Select.zig+20-20
......@@ -2099,7 +2099,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
20992099 32 => "truncf",
21002100 64 => "trunc",
21012101 80 => "__truncx",
2102 128 => "truncq",
2102 128 => "truncf128",
21032103 },
21042104 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
21052105 });
......@@ -2113,7 +2113,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
21132113 32 => "floorf",
21142114 64 => "floor",
21152115 80 => "__floorx",
2116 128 => "floorq",
2116 128 => "floorf128",
21172117 },
21182118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
21192119 });
......@@ -2431,7 +2431,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
24312431 32 => "fmodf",
24322432 64 => "fmod",
24332433 80 => "__fmodx",
2434 128 => "fmodq",
2434 128 => "fmodf128",
24352435 },
24362436 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
24372437 });
......@@ -2599,7 +2599,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
25992599 32 => "fmaxf",
26002600 64 => "fmax",
26012601 80 => "__fmaxx",
2602 128 => "fmaxq",
2602 128 => "fmaxf128",
26032603 },
26042604 .min => switch (bits) {
26052605 else => unreachable,
......@@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
26072607 32 => "fminf",
26082608 64 => "fmin",
26092609 80 => "__fminx",
2610 128 => "fminq",
2610 128 => "fminf128",
26112611 },
26122612 },
26132613 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
......@@ -4055,7 +4055,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40554055 32 => "sqrtf",
40564056 64 => "sqrt",
40574057 80 => "__sqrtx",
4058 128 => "sqrtq",
4058 128 => "sqrtf128",
40594059 },
40604060 .floor => switch (bits) {
40614061 else => unreachable,
......@@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40634063 32 => "floorf",
40644064 64 => "floor",
40654065 80 => "__floorx",
4066 128 => "floorq",
4066 128 => "floorf128",
40674067 },
40684068 .ceil => switch (bits) {
40694069 else => unreachable,
......@@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40714071 32 => "ceilf",
40724072 64 => "ceil",
40734073 80 => "__ceilx",
4074 128 => "ceilq",
4074 128 => "ceilf128",
40754075 },
40764076 .round => switch (bits) {
40774077 else => unreachable,
......@@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40794079 32 => "roundf",
40804080 64 => "round",
40814081 80 => "__roundx",
4082 128 => "roundq",
4082 128 => "roundf128",
40834083 },
40844084 .trunc_float => switch (bits) {
40854085 else => unreachable,
......@@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
40874087 32 => "truncf",
40884088 64 => "trunc",
40894089 80 => "__truncx",
4090 128 => "truncq",
4090 128 => "truncf128",
40914091 },
40924092 },
40934093 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
......@@ -4147,7 +4147,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41474147 32 => "sinf",
41484148 64 => "sin",
41494149 80 => "__sinx",
4150 128 => "sinq",
4150 128 => "sinf128",
41514151 },
41524152 .cos => switch (bits) {
41534153 else => unreachable,
......@@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41554155 32 => "cosf",
41564156 64 => "cos",
41574157 80 => "__cosx",
4158 128 => "cosq",
4158 128 => "cosf128",
41594159 },
41604160 .tan => switch (bits) {
41614161 else => unreachable,
......@@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41634163 32 => "tanf",
41644164 64 => "tan",
41654165 80 => "__tanx",
4166 128 => "tanq",
4166 128 => "tanf128",
41674167 },
41684168 .exp => switch (bits) {
41694169 else => unreachable,
......@@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41714171 32 => "expf",
41724172 64 => "exp",
41734173 80 => "__expx",
4174 128 => "expq",
4174 128 => "expf128",
41754175 },
41764176 .exp2 => switch (bits) {
41774177 else => unreachable,
......@@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41794179 32 => "exp2f",
41804180 64 => "exp2",
41814181 80 => "__exp2x",
4182 128 => "exp2q",
4182 128 => "exp2f128",
41834183 },
41844184 .log => switch (bits) {
41854185 else => unreachable,
......@@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41874187 32 => "logf",
41884188 64 => "log",
41894189 80 => "__logx",
4190 128 => "logq",
4190 128 => "logf128",
41914191 },
41924192 .log2 => switch (bits) {
41934193 else => unreachable,
......@@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
41954195 32 => "log2f",
41964196 64 => "log2",
41974197 80 => "__log2x",
4198 128 => "log2q",
4198 128 => "log2f128",
41994199 },
42004200 .log10 => switch (bits) {
42014201 else => unreachable,
......@@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
42034203 32 => "log10f",
42044204 64 => "log10",
42054205 80 => "__log10x",
4206 128 => "log10q",
4206 128 => "log10f128",
42074207 },
42084208 },
42094209 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
......@@ -7118,7 +7118,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
71187118 32 => "fmaf",
71197119 64 => "fma",
71207120 80 => "__fmax",
7121 128 => "fmaq",
7121 128 => "fmaf128",
71227122 },
71237123 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
71247124 });
......@@ -12388,7 +12388,7 @@ pub const CallAbiIterator = struct {
1238812388 .f32 => .single,
1238912389 .f64 => .double,
1239012390 .f128 => .quad,
12391 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) {
12391 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble).?) {
1239212392 else => unreachable,
1239312393 64 => .double,
1239412394 80 => null,
src/codegen/aarch64/abi.zig+7-2
......@@ -1,4 +1,4 @@
1const assert = @import("std").debug.assert;
1const assert = std.debug.assert;
22const std = @import("std");
33const InternPool = @import("../../InternPool.zig");
44const Type = @import("../../Type.zig");
......@@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
3535 if (bit_size > 64) return .double_integer;
3636 return .integer;
3737 },
38 .int, .@"enum", .error_set, .float, .bool => return .byval,
38 .int, .@"enum", .error_set, .bool => return .byval,
39 .float => return switch (ty.floatBits(zcu.getTarget())) {
40 else => unreachable,
41 16, 32, 64, 128 => .byval,
42 80 => .double_integer,
43 },
3944 .vector => {
4045 const bit_size = ty.bitSize(zcu);
4146 // TODO is this controlled by a cpu feature?
src/codegen/arm/abi.zig+9-7
......@@ -39,7 +39,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
3939 const float_count = countFloats(ty, zcu, &maybe_float_bits);
4040 if (float_count <= byval_float_count) return .byval;
4141
42 if (ty.abiAlignment(zcu).compare(.gt, .@"32")) {
42 if (ty.abiAlignment(zcu).compare(.gt, .@"4")) {
4343 return Class.arrSize(bit_size, 64);
4444 }
4545
......@@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
6262 const float_count = countFloats(ty, zcu, &maybe_float_bits);
6363 if (float_count <= byval_float_count) return .byval;
6464
65 if (union_obj.alignment.compareStrict(.gt, .@"32")) {
65 if (union_obj.alignment.compareStrict(.gt, .@"4")) {
6666 return Class.arrSize(bit_size, 64);
6767 }
6868
......@@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
7373 }
7474 return Class.arrSize(bit_size, 32);
7575 },
76 .bool, .float => return .byval,
76 .bool => return .byval,
7777 .int => {
78 // TODO this is incorrect for _BitInt(128) but implementing
79 // this correctly makes implementing compiler-rt impossible.
80 // const bit_size = ty.bitSize(zcu);
81 // if (bit_size > 64) return .memory;
78 if (ctx == .ret and ty.intInfo(zcu).bits > 64) return .memory;
8279 return .byval;
8380 },
81 .float => return switch (ty.floatBits(zcu.getTarget())) {
82 else => unreachable,
83 16, 32, 64 => .byval,
84 80, 128 => .{ .i64_array = 2 },
85 },
8486 .@"enum", .error_set => {
8587 const bit_size = ty.bitSize(zcu);
8688 if (bit_size > 64) return .memory;
src/codegen/c.zig+745-604
......@@ -164,7 +164,8 @@ const BlockData = struct {
164164
165165const LocalType = struct {
166166 type: Type,
167 alignment: Alignment,
167 alignment: Alignment = .none,
168 array_len: u2 = 1,
168169};
169170
170171const LocalIndex = u16;
......@@ -184,13 +185,11 @@ const ValueRenderLocation = enum {
184185 }
185186};
186187
187const BuiltinInfo = enum { none, bits };
188const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits };
188189
189190const reserved_idents = std.StaticStringMap(void).initComptime(.{
190191 // C language
191 .{ "alignas", {
192 @setEvalBranchQuota(4000);
193 } },
192 .{ "alignas", {} },
194193 .{ "alignof", {} },
195194 .{ "asm", {} },
196195 .{ "atomic_bool", {} },
......@@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{
302301 // stddef.h
303302 .{ "offsetof", {} },
304303
304 // math.h (only symbols exported by compiler-rt)
305 .{ "ceil", {} },
306 .{ "ceilf", {} },
307 .{ "ceilf128", {} },
308 .{ "ceill", {} },
309 .{ "cos", {} },
310 .{ "cosf", {} },
311 .{ "cosf128", {} },
312 .{ "cosl", {} },
313 .{ "exp", {} },
314 .{ "exp2", {} },
315 .{ "exp2f", {} },
316 .{ "exp2f128", {} },
317 .{ "exp2l", {} },
318 .{ "expf", {} },
319 .{ "expf128", {} },
320 .{ "expl", {} },
321 .{ "fabs", {} },
322 .{ "fabsf", {} },
323 .{ "fabsf128", {} },
324 .{ "fabsl", {} },
325 .{ "floor", {} },
326 .{ "floorf", {} },
327 .{ "floorf128", {} },
328 .{ "floorl", {} },
329 .{ "fma", {} },
330 .{ "fmaf", {} },
331 .{ "fmaf128", {} },
332 .{ "fmal", {} },
333 .{ "fmax", {} },
334 .{ "fmaxf", {} },
335 .{ "fmaxf128", {} },
336 .{ "fmaxl", {} },
337 .{ "fmin", {} },
338 .{ "fminf", {} },
339 .{ "fminf128", {} },
340 .{ "fminl", {} },
341 .{ "fmod", {} },
342 .{ "fmodf", {} },
343 .{ "fmodf128", {} },
344 .{ "fmodl", {} },
345 .{ "log", {} },
346 .{ "log10", {} },
347 .{ "log10f", {} },
348 .{ "log10f128", {} },
349 .{ "log10l", {} },
350 .{ "log2", {} },
351 .{ "log2f", {} },
352 .{ "log2f128", {} },
353 .{ "log2l", {} },
354 .{ "logf", {} },
355 .{ "logf128", {} },
356 .{ "logl", {} },
357 .{ "round", {} },
358 .{ "roundf", {} },
359 .{ "roundf128", {} },
360 .{ "roundl", {} },
361 .{ "sin", {} },
362 .{ "sincos", {} },
363 .{ "sincosf", {} },
364 .{ "sincosf128", {} },
365 .{ "sincosl", {} },
366 .{ "sinf", {} },
367 .{ "sinf128", {} },
368 .{ "sinl", {} },
369 .{ "sqrt", {} },
370 .{ "sqrtf", {} },
371 .{ "sqrtf128", {} },
372 .{ "sqrtl", {} },
373 .{ "tan", {} },
374 .{ "tanf", {} },
375 .{ "tanf128", {} },
376 .{ "tanl", {} },
377 .{ "trunc", {} },
378 .{ "truncf", {} },
379 .{ "truncf128", {} },
380 .{ "truncl", {} },
381
305382 // windows.h
383 .{"DUMMYSTRUCTNAME"},
384 .{"DUMMYSTRUCTNAME2"},
385 .{"DUMMYSTRUCTNAME3"},
386 .{"DUMMYSTRUCTNAME4"},
387 .{"DUMMYSTRUCTNAME5"},
388 .{"DUMMYSTRUCTNAME6"},
389 .{"DUMMYUNIONNAME"},
390 .{"DUMMYUNIONNAME2"},
391 .{"DUMMYUNIONNAME3"},
392 .{"DUMMYUNIONNAME4"},
393 .{"DUMMYUNIONNAME5"},
394 .{"DUMMYUNIONNAME6"},
395 .{"DUMMYUNIONNAME7"},
396 .{"DUMMYUNIONNAME8"},
397 .{"DUMMYUNIONNAME9"},
306398 .{ "max", {} },
307399 .{ "min", {} },
308400});
......@@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool {
316408 }
317409 }
318410
319 // windows.h
320 if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or
321 mem.startsWith(u8, ident, "DUMMYUNIONNAME"))
322 {
323 return true;
324 }
325
326411 // CType
327412 if (mem.startsWith(u8, ident, "enum__") or
328413 mem.startsWith(u8, ident, "bitpack__") or
......@@ -469,10 +554,7 @@ pub const Function = struct {
469554 }
470555
471556 fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue {
472 return f.allocAlignedLocal(inst, .{
473 .type = ty,
474 .alignment = .none,
475 });
557 return f.allocAlignedLocal(inst, .{ .type = ty });
476558 }
477559
478560 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
......@@ -564,10 +646,6 @@ pub const Function = struct {
564646 return f.dg.renderType(w, ty);
565647 }
566648
567 fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
568 return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
569 }
570
571649 fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) {
572650 return f.dg.fmtIntLiteralDec(val, .other);
573651 }
......@@ -672,7 +750,9 @@ pub const DeclGen = struct {
672750 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
673751 const ptr_ty: Type = .fromInterned(uav.orig_ty);
674752 if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
675 return dg.renderUndefValue(w, ptr_ty, location);
753 try w.writeByte('(');
754 try dg.renderOpvPointer(w, ptr_ty, location);
755 return w.writeByte(')');
676756 }
677757
678758 switch (ip.indexToKey(uav.val)) {
......@@ -737,8 +817,10 @@ pub const DeclGen = struct {
737817 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
738818 const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type);
739819 const ptr_ty = try pt.navPtrType(owner_nav);
740 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
741 return dg.renderUndefValue(w, ptr_ty, location);
820 if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
821 try w.writeByte('(');
822 try dg.renderOpvPointer(w, ptr_ty, location);
823 return w.writeByte(')');
742824 }
743825
744826 // We shouldn't cast C function pointers as this is UB (when you call
......@@ -758,6 +840,26 @@ pub const DeclGen = struct {
758840 if (need_cast) try w.writeByte(')');
759841 }
760842
843 fn renderOpvPointer(
844 dg: *DeclGen,
845 w: *Writer,
846 ptr_ty: Type,
847 location: ValueRenderLocation,
848 ) Error!void {
849 const zcu = dg.pt.zcu;
850 const target = zcu.getTarget();
851 try w.writeByte('(');
852 try dg.renderType(w, ptr_ty);
853 return w.print("){f}", .{fmtUnsignedIntLiteralSmall(
854 target,
855 .uintptr_t,
856 ptr_ty.ptrAlignment(zcu).forward(undefPattern(u64) >> @intCast(64 - target.ptrBitWidth())),
857 location == .static_initializer,
858 16,
859 .lower,
860 )});
861 }
862
761863 fn renderPointer(
762864 dg: *DeclGen,
763865 w: *Writer,
......@@ -959,9 +1061,6 @@ pub const DeclGen = struct {
9591061 const bits = ty.floatBits(target);
9601062 const f128_val = val.toFloat(f128, zcu);
9611063
962 // All unsigned ints matching float types are pre-allocated.
963 const repr_ty = pt.intType(.unsigned, bits) catch unreachable;
964
9651064 assert(bits <= 128);
9661065 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
9671066 var repr_val_big = BigInt.Mutable{
......@@ -971,29 +1070,27 @@ pub const DeclGen = struct {
9711070 };
9721071
9731072 switch (bits) {
1073 else => unreachable,
9741074 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))),
9751075 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))),
9761076 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))),
9771077 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))),
9781078 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))),
979 else => unreachable,
9801079 }
9811080
982 var empty = true;
9831081 if (std.math.isFinite(f128_val)) {
9841082 try w.writeAll("zig_make_");
9851083 try dg.renderTypeForBuiltinFnName(w, ty);
9861084 try w.writeByte('(');
9871085 switch (bits) {
1086 else => unreachable,
9881087 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}),
9891088 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}),
9901089 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}),
9911090 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}),
9921091 128 => try w.print("{x}", .{f128_val}),
993 else => unreachable,
9941092 }
9951093 try w.writeAll(", ");
996 empty = false;
9971094 } else {
9981095 // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan
9991096 const operation = if (std.math.isNan(f128_val))
......@@ -1028,6 +1125,7 @@ pub const DeclGen = struct {
10281125 try w.writeAll(operation);
10291126 try w.writeAll(", ");
10301127 if (std.math.isNan(f128_val)) switch (bits) {
1128 else => unreachable,
10311129 // We only actually need to pass the significand, but it will get
10321130 // properly masked anyway, so just pass the whole value.
10331131 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
......@@ -1035,16 +1133,23 @@ pub const DeclGen = struct {
10351133 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
10361134 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
10371135 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
1038 else => unreachable,
10391136 };
10401137 try w.writeAll(", ");
1041 empty = false;
10421138 }
1043 try w.print("{f}", .{try dg.fmtIntLiteralHex(
1044 try pt.intValue_big(repr_ty, repr_val_big.toConst()),
1045 location,
1046 )});
1047 if (!empty) try w.writeByte(')');
1139 switch (bits) {
1140 else => unreachable,
1141 16, 32, 64 => {
1142 // All unsigned ints matching float types are pre-allocated.
1143 const repr_ty = pt.intType(.unsigned, bits) catch unreachable;
1144 try w.print("{f}", .{try dg.fmtIntLiteralHex(
1145 try pt.intValue_big(repr_ty, repr_val_big.toConst()),
1146 location,
1147 )});
1148 },
1149 80 => try F80Repr.write(@bitCast(val.toFloat(f80, zcu)), w, target, location == .static_initializer),
1150 128 => try F128Repr.write(@bitCast(f128_val), w, target, location == .static_initializer),
1151 }
1152 try w.writeByte(')');
10481153 },
10491154 .slice => |slice| {
10501155 if (!location.isInitializer()) {
......@@ -1319,22 +1424,29 @@ pub const DeclGen = struct {
13191424 .f128_type,
13201425 => {
13211426 const bits = ty.floatBits(target);
1322 // All unsigned ints matching float types are pre-allocated.
1323 const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;
13241427
13251428 try w.writeAll("zig_make_");
13261429 try dg.renderTypeForBuiltinFnName(w, ty);
13271430 try w.writeByte('(');
13281431 switch (bits) {
1329 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
1330 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
1331 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
1332 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
1333 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
13341432 else => unreachable,
1433 16 => try w.print("{x}", .{undefPattern(f16)}),
1434 32 => try w.print("{x}", .{undefPattern(f32)}),
1435 64 => try w.print("{x}", .{undefPattern(f64)}),
1436 80 => try w.print("{x}", .{undefPattern(f80)}),
1437 128 => try w.print("{x}", .{undefPattern(f128)}),
13351438 }
13361439 try w.writeAll(", ");
1337 try dg.renderUndefValue(w, repr_ty, .other);
1440 switch (bits) {
1441 else => unreachable,
1442 16, 32, 64 => {
1443 // All unsigned ints matching float types are pre-allocated.
1444 const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;
1445 try dg.renderUndefValue(w, repr_ty, .other);
1446 },
1447 80 => try undefPattern(F80Repr).write(w, target, location == .static_initializer),
1448 128 => try undefPattern(F128Repr).write(w, target, location == .static_initializer),
1449 }
13381450 return w.writeByte(')');
13391451 },
13401452 .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"),
......@@ -1638,8 +1750,6 @@ pub const DeclGen = struct {
16381750 try w.writeAll("zig_no_builtin ");
16391751 }
16401752
1641 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
1642
16431753 // While incomplete types are usually an acceptable substitute for "void", this is not true
16441754 // in function return types, where "void" is the only incomplete type permitted.
16451755 const actual_return_type: Type = .fromInterned(fn_info.return_type);
......@@ -1651,8 +1761,9 @@ pub const DeclGen = struct {
16511761
16521762 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);
16531763 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
1654 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
1655 try w.print("zig_callconv({s}) ", .{call_conv});
1764 switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) {
1765 .c => {},
1766 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
16561767 }
16571768 switch (name) {
16581769 .nav => |nav| try renderNavName(w, nav, ip),
......@@ -1726,136 +1837,6 @@ pub const DeclGen = struct {
17261837 try w.print("{f}", .{cty.fmtTypeName(zcu)});
17271838 }
17281839
1729 const IntCastContext = union(enum) {
1730 c_value: struct {
1731 f: *Function,
1732 value: CValue,
1733 v: Vectorize,
1734 },
1735 value: struct {
1736 value: Value,
1737 },
1738
1739 pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void {
1740 switch (self.*) {
1741 .c_value => |v| {
1742 try v.f.writeCValue(w, v.value, location);
1743 try v.v.elem(v.f, w);
1744 },
1745 .value => |v| try dg.renderValue(w, v.value, location),
1746 }
1747 }
1748 };
1749 fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool {
1750 const pt = dg.pt;
1751 const zcu = pt.zcu;
1752 const dest_bits = dest_ty.bitSize(zcu);
1753 const dest_int_info = dest_ty.intInfo(pt.zcu);
1754
1755 const src_is_ptr = src_ty.isPtrAtRuntime(pt.zcu);
1756 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
1757 .unsigned => .usize,
1758 .signed => .isize,
1759 } else src_ty;
1760
1761 const src_bits = src_eff_ty.bitSize(zcu);
1762 const src_int_info = if (src_eff_ty.isAbiInt(pt.zcu)) src_eff_ty.intInfo(pt.zcu) else null;
1763 if (dest_bits <= 64 and src_bits <= 64) {
1764 const needs_cast = src_int_info == null or
1765 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
1766 dest_int_info.signedness != src_int_info.?.signedness);
1767 return !needs_cast and !src_is_ptr;
1768 } else return false;
1769 }
1770 /// Renders a cast to an int type, from either an int or a pointer.
1771 ///
1772 /// Some platforms don't have 128 bit integers, so we need to use
1773 /// the zig_make_ and zig_lo_ macros in those cases.
1774 ///
1775 /// | Dest type bits | Src type | Result
1776 /// |------------------|------------------|---------------------------|
1777 /// | < 64 bit integer | pointer | (zig_<dest_ty>)(zig_<u|i>size)src
1778 /// | < 64 bit integer | < 64 bit integer | (zig_<dest_ty>)src
1779 /// | < 64 bit integer | > 64 bit integer | zig_lo(src)
1780 /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src)
1781 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
1782 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
1783 fn renderIntCast(
1784 dg: *DeclGen,
1785 w: *Writer,
1786 dest_ty: Type,
1787 context: IntCastContext,
1788 src_ty: Type,
1789 location: ValueRenderLocation,
1790 ) !void {
1791 const pt = dg.pt;
1792 const zcu = pt.zcu;
1793 const dest_bits = dest_ty.bitSize(zcu);
1794 const dest_int_info = dest_ty.intInfo(zcu);
1795
1796 const src_is_ptr = src_ty.isPtrAtRuntime(zcu);
1797 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
1798 .unsigned => .usize,
1799 .signed => .isize,
1800 } else src_ty;
1801
1802 const src_bits = src_eff_ty.bitSize(zcu);
1803 const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null;
1804 if (dest_bits <= 64 and src_bits <= 64) {
1805 const needs_cast = src_int_info == null or
1806 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
1807 dest_int_info.signedness != src_int_info.?.signedness);
1808
1809 if (needs_cast) {
1810 try w.writeByte('(');
1811 try dg.renderType(w, dest_ty);
1812 try w.writeByte(')');
1813 }
1814 if (src_is_ptr) {
1815 try w.writeByte('(');
1816 try dg.renderType(w, src_eff_ty);
1817 try w.writeByte(')');
1818 }
1819 try context.writeValue(dg, w, location);
1820 } else if (dest_bits <= 64 and src_bits > 64) {
1821 assert(!src_is_ptr);
1822 if (dest_bits < 64) {
1823 try w.writeByte('(');
1824 try dg.renderType(w, dest_ty);
1825 try w.writeByte(')');
1826 }
1827 try w.writeAll("zig_lo_");
1828 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
1829 try w.writeByte('(');
1830 try context.writeValue(dg, w, .other);
1831 try w.writeByte(')');
1832 } else if (dest_bits > 64 and src_bits <= 64) {
1833 try w.writeAll("zig_make_");
1834 try dg.renderTypeForBuiltinFnName(w, dest_ty);
1835 try w.writeAll("(0, ");
1836 if (src_is_ptr) {
1837 try w.writeByte('(');
1838 try dg.renderType(w, src_eff_ty);
1839 try w.writeByte(')');
1840 }
1841 try context.writeValue(dg, w, .other);
1842 try w.writeByte(')');
1843 } else {
1844 assert(!src_is_ptr);
1845 try w.writeAll("zig_make_");
1846 try dg.renderTypeForBuiltinFnName(w, dest_ty);
1847 try w.writeAll("(zig_hi_");
1848 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
1849 try w.writeByte('(');
1850 try context.writeValue(dg, w, .other);
1851 try w.writeAll("), zig_lo_");
1852 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
1853 try w.writeByte('(');
1854 try context.writeValue(dg, w, .other);
1855 try w.writeAll("))");
1856 }
1857 }
1858
18591840 /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type.
18601841 fn renderTypeAndName(
18611842 dg: *DeclGen,
......@@ -2000,6 +1981,7 @@ pub const DeclGen = struct {
20001981 switch (info) {
20011982 .none => if (!is_big) return,
20021983 .bits => {},
1984 .bits_none, .big_temp_bits => unreachable,
20031985 }
20041986
20051987 const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{
......@@ -2056,6 +2038,72 @@ const CQualifiers = packed struct {
20562038 restrict: bool = false,
20572039};
20582040
2041pub fn genHeader(zcu: *Zcu, w: *Writer) !void {
2042 const gpa = zcu.comp.gpa;
2043
2044 var arena: std.heap.ArenaAllocator = .init(gpa);
2045 defer arena.deinit();
2046 var ctype_deps: CType.Dependencies = .empty;
2047 defer ctype_deps.deinit(gpa);
2048
2049 const target = zcu.getTarget();
2050 switch (target.abi) {
2051 .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
2052 else => {},
2053 }
2054 for ([_]u16{ 16, 32, 64, 80, 128 }) |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2055 .hard => {},
2056 .soft => try w.print("#define ZIG_TARGET_SOFT_COMPILER_RT_F{d}_ABI\n", .{bits}),
2057 };
2058 try w.print(
2059 \\#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}
2060 \\#include "zig.h"
2061 \\
2062 \\
2063 ,
2064 .{target.cMaxIntAlignment()},
2065 );
2066
2067 var basic_ty: Type = .fromInterned(.first_type);
2068 while (true) : ({
2069 basic_ty = .fromInterned(@fromBackingInt(@intCast(@backingInt(basic_ty.toIntern()) + 1)));
2070 if (basic_ty.toIntern() == InternPool.Index.last_type) break;
2071 }) {
2072 switch (basic_ty.toIntern()) {
2073 else => {},
2074 .anyframe_type,
2075 .adhoc_inferred_error_set_type,
2076 .generic_poison_type,
2077 => continue, // skip unsupported types
2078 }
2079 const basic_cty: CType = try .lower(basic_ty, &ctype_deps, arena.allocator(), zcu);
2080 switch (basic_cty) {
2081 .void => {}, // no layout to check
2082 .bool,
2083 .int,
2084 .float,
2085 => try CType.render_defs.writeStaticAssertTypeLayout(basic_ty, basic_cty, w, zcu),
2086 .@"fn",
2087 .@"enum",
2088 .bitpack,
2089 .@"struct",
2090 .union_auto,
2091 .union_extern,
2092 .slice,
2093 .opt,
2094 .arr,
2095 .vec,
2096 .errunion,
2097 .aligned,
2098 .bigint,
2099 .pointer,
2100 .array,
2101 .function,
2102 => {},
2103 }
2104 }
2105}
2106
20592107pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
20602108 for (zcu.global_assembly.values()) |asm_source| {
20612109 try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)});
......@@ -2070,16 +2118,16 @@ pub fn genErrDecls(
20702118 const ip = &zcu.intern_pool;
20712119
20722120 const names = ip.global_error_set.getNamesFromMainThread();
2073 // Don't generate an invalid empty enum if the global error set is empty!
2074 if (names.len > 0) {
2075 try w.writeAll("enum {\n");
2076 for (names, 1..) |name_nts, value| {
2077 try w.writeByte(' ');
2078 try renderErrorName(w, name_nts.toSlice(ip));
2079 try w.print(" = {d}u,\n", .{value});
2080 }
2081 try w.writeAll("};\n");
2121 // Don't generate an invalid empty enum/array if the global error set is empty!
2122 if (names.len == 0) return;
2123
2124 try w.writeAll("enum {\n");
2125 for (names, 1..) |name_nts, value| {
2126 try w.writeByte(' ');
2127 try renderErrorName(w, name_nts.toSlice(ip));
2128 try w.print(" = {d}u,\n", .{value});
20822129 }
2130 try w.writeAll("};\n");
20832131
20842132 for (names) |name_nts| {
20852133 const name = name_nts.toSlice(ip);
......@@ -2093,7 +2141,7 @@ pub fn genErrDecls(
20932141 "static {s} const zig_errorName[{d}] = {{",
20942142 .{ slice_const_u8_sentinel_0_type_name, names.len },
20952143 );
2096 if (names.len > 0) try w.writeByte('\n');
2144 try w.writeByte('\n');
20972145 for (names) |name_nts| {
20982146 const name = name_nts.toSlice(ip);
20992147 try w.print(
......@@ -2114,10 +2162,18 @@ pub fn genTagNameFn(
21142162 const ip = &zcu.intern_pool;
21152163 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
21162164 assert(loaded_enum.field_names.len > 0);
2117 if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) {
2118 @panic("TODO CBE: tagName for enum over 64 bits");
2165 switch (CType.classifyInt(enum_ty, zcu)) {
2166 .void => unreachable,
2167 .small => |int| switch (int) {
2168 else => {},
2169 .zig_u128, .zig_i128 => @panic("TODO CBE: tagName for 128-bit enums"),
2170 },
2171 .big => @panic("TODO CBE: tagName for bigint enums"),
21192172 }
21202173
2174 if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{
2175 loaded_enum.name.fmt(ip),
2176 });
21212177 try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{
21222178 slice_const_u8_sentinel_0_type_name,
21232179 fmtIdentUnsolo(loaded_enum.name.toSlice(ip)),
......@@ -2164,6 +2220,7 @@ pub fn genLazyCallModifierFn(
21642220
21652221 const fn_val = zcu.navValue(fn_nav);
21662222
2223 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
21672224 try w.print("static zig_{t} ", .{kind});
21682225 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {
21692226 .never_tail => .{ .nav_never_tail = fn_nav },
......@@ -2269,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
22692326 const gpa = f.dg.gpa;
22702327 const nav_index = f.dg.owner_nav.unwrap().?;
22712328 const nav_val = zcu.navValue(nav_index);
2329 const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?;
22722330 const nav = ip.getNav(nav_index);
22732331
2332 if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn ");
22742333 try fwd_decl_writer.writeAll("static ");
22752334 try f.dg.renderFunctionSignature(
22762335 fwd_decl_writer,
......@@ -2291,11 +2350,41 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
22912350 .{ .nav = nav_index },
22922351 );
22932352 try header_writer.writeAll(" {\n ");
2353 if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)});
22942354
22952355 f.free_locals_map.clearRetainingCapacity();
22962356
22972357 const main_body = f.air.getMainBody();
22982358 f.indent();
2359 if (switch (fn_info.cc) {
2360 inline else => |pl| switch (@TypeOf(pl)) {
2361 void,
2362 std.lang.CallingConvention.SpirvKernelOptions,
2363 std.lang.CallingConvention.SpirvFragmentOptions,
2364 std.lang.CallingConvention.SpirvMeshOptions,
2365 => null,
2366 std.lang.CallingConvention.ArcInterruptOptions,
2367 std.lang.CallingConvention.ArmInterruptOptions,
2368 std.lang.CallingConvention.RiscvInterruptOptions,
2369 std.lang.CallingConvention.ShInterruptOptions,
2370 std.lang.CallingConvention.MicroblazeInterruptOptions,
2371 std.lang.CallingConvention.MipsInterruptOptions,
2372 std.lang.CallingConvention.CommonOptions,
2373 std.lang.CallingConvention.X86RegparmOptions,
2374 => pl.incoming_stack_alignment,
2375 else => @compileError(@tagName(pl)),
2376 },
2377 }) |incoming_stack_alignment| realign_stack: {
2378 const normal_stack_align = zcu.getTarget().stackAlignment();
2379 if (incoming_stack_alignment >= normal_stack_align) break :realign_stack;
2380 try header_writer.print("char zig_align({d}) zig_realign_stack;\n ", .{
2381 normal_stack_align << 1,
2382 });
2383 try f.code.writer.writeAll(
2384 \\__asm volatile("" :: [zig_realign_stack] "m" (zig_realign_stack));
2385 );
2386 try f.newline();
2387 }
22992388 try genBodyResolveState(f, undefined, &.{}, main_body, true);
23002389 try f.outdent();
23012390 try f.code.writer.writeByte('}');
......@@ -2346,6 +2435,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
23462435 for (list.keys()) |local_index| {
23472436 const local = f.locals.items[local_index];
23482437 try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment);
2438 if (local.array_len != 1) try header_writer.print("[{d}]", .{local.array_len});
23492439 try header_writer.writeAll(";\n ");
23502440 }
23512441 }
......@@ -2397,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
23972487
23982488 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
23992489 .@"fn" => {
2490 const fn_val: Value = .fromInterned(nav.resolved.?.value);
2491 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
24002492 try w.writeAll("zig_extern ");
24012493 try dg.renderFunctionSignature(
24022494 w,
2403 .fromInterned(nav.resolved.?.value),
2495 fn_val,
24042496 nav.resolved.?.@"align",
24052497 .forward_decl,
24062498 .{ .@"export" = .{
......@@ -2461,7 +2553,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct {
24612553 try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none);
24622554 try w.writeAll(" = ");
24632555 try dg.renderValue(w, options.init_val, .static_initializer);
2464 try w.writeAll(";\n");
2556 try w.writeByte(';');
2557 if (dg.owner_nav.unwrap()) |nav_index| {
2558 const ip = &zcu.intern_pool;
2559 if (!dg.mod.strip) try w.print(" /* {f} */", .{ip.getNav(nav_index).fqn.fmt(ip)});
2560 }
2561 try w.writeByte('\n');
24652562}
24662563pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct {
24672564 name: CValue,
......@@ -2496,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
24962593 const exported_val = exported.getValue(zcu);
24972594 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {
24982595 const @"export" = export_index.ptr(zcu);
2596 const fn_val = exported.getValue(zcu);
2597 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
24992598 try w.writeAll("zig_extern ");
25002599 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");
25012600 try dg.renderFunctionSignature(
25022601 w,
2503 exported.getValue(zcu),
2602 fn_val,
25042603 exported.getAlign(zcu),
25052604 .forward_decl,
25062605 .{ .@"export" = .{
......@@ -2662,22 +2761,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
26622761 .mul => try airBinOp(f, inst, "*", "mul", .none),
26632762
26642763 .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none),
2665 .div_float => try airBinBuiltinCall(f, inst, "div", .none),
2764 .div_float => try airBinBuiltinCall(f, inst, "div", .big_temp_bits),
26662765
2667 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
2766 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "divTrunc", .big_temp_bits),
26682767 .rem => blk: {
26692768 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
26702769 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);
26712770 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
26722771 // so we only check one.
26732772 break :blk if (lhs_scalar_ty.isInt(zcu))
2674 try airBinOp(f, inst, "%", "rem", .none)
2773 try airBinOp(f, inst, "%", "rem", .big_temp_bits)
26752774 else
26762775 try airBinBuiltinCall(f, inst, "fmod", .none);
26772776 },
2678 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),
2679 .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none),
2680 .mod => try airBinBuiltinCall(f, inst, "mod", .none),
2777 .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits),
2778 .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits),
2779 .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits),
26812780 .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none),
26822781
26832782 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),
......@@ -2687,7 +2786,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
26872786 .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits),
26882787 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits),
26892788 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits),
2690 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits),
2789 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits_none),
26912790
26922791 .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none),
26932792 .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none),
......@@ -2764,8 +2863,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
27642863 .int_from_error => try airNopCast(f, inst),
27652864 .union_from_enum => try airUnionFromEnum(f, inst),
27662865 .bit_cast => try airBitCast(f, inst),
2767 .int_cast => try airIntCast(f, inst),
2768 .trunc => try airTrunc(f, inst),
2866 .int_cast => try airIntCast(f, inst, "intCast", .none),
2867 .trunc => try airIntCast(f, inst, "truncate", .bits),
27692868 .load => try airLoad(f, inst),
27702869 .store => try airStore(f, inst, false),
27712870 .store_safe => try airStore(f, inst, true),
......@@ -2783,9 +2882,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
27832882 .get_union_tag => try airGetUnionTag(f, inst),
27842883 .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits),
27852884 .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits),
2786 .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popcount", .bits),
2787 .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits),
2788 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits),
2885 .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popCount", .bits),
2886 .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits),
2887 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits),
27892888 .tag_name => try airTagName(f, inst),
27902889 .error_name => try airErrorName(f, inst),
27912890 .splat => try airSplat(f, inst),
......@@ -3124,7 +3223,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
31243223 const zcu = pt.zcu;
31253224 const inst_ty = f.typeOfIndex(inst);
31263225 const elem_ty = inst_ty.childType(zcu);
3127 if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty };
3226 if (!elem_ty.hasRuntimeBits(zcu)) {
3227 const w = &f.code.writer;
3228 const local = try f.allocLocal(inst, inst_ty);
3229 try f.writeCValue(w, local, .other);
3230 try w.writeAll(" = ");
3231 try f.dg.renderOpvPointer(w, inst_ty, .other);
3232 try w.writeByte(';');
3233 try f.newline();
3234 return local;
3235 }
31283236
31293237 const local = try f.allocLocalValue(.{
31303238 .type = elem_ty,
......@@ -3298,120 +3406,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
32983406 }
32993407}
33003408
3301fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3409fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
33023410 const pt = f.dg.pt;
33033411 const zcu = pt.zcu;
33043412 const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op;
33053413
3306 const operand = try f.resolveInst(ty_op.operand);
3307 try reap(f, inst, &.{ty_op.operand});
3308
3309 const inst_ty = f.typeOfIndex(inst);
3414 const inst_ty = ty_op.ty.toType();
33103415 const inst_scalar_ty = inst_ty.scalarType(zcu);
33113416 const operand_ty = f.typeOf(ty_op.operand);
3312 const scalar_ty = operand_ty.scalarType(zcu);
3313
3314 // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct.
3315 if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) {
3316 return f.moveCValue(inst, inst_ty, operand);
3317 }
3318
3319 const w = &f.code.writer;
3320 const local = try f.allocLocal(inst, inst_ty);
3321 const v = try Vectorize.start(f, inst, w, operand_ty);
3322 try f.writeCValue(w, local, .other);
3323 try v.elem(f, w);
3324 try w.writeAll(" = ");
3325 try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other);
3326 try w.writeByte(';');
3327 try f.newline();
3328 try v.end(f, inst, w);
3329 return local;
3330}
3331
3332fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3333 const pt = f.dg.pt;
3334 const zcu = pt.zcu;
3335 const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op;
3417 const operand_scalar_ty = operand_ty.scalarType(zcu);
3418 const is_big = lowersToBigInt(operand_ty, zcu);
33363419
33373420 const operand = try f.resolveInst(ty_op.operand);
3338 try reap(f, inst, &.{ty_op.operand});
3421 if (!is_big) try reap(f, inst, &.{ty_op.operand});
33393422
3340 const inst_ty = f.typeOfIndex(inst);
3341 const inst_scalar_ty = inst_ty.scalarType(zcu);
3342 const dest_int_info = inst_scalar_ty.intInfo(zcu);
3343 const dest_bits = dest_int_info.bits;
3344 const dest_c_bits = toCIntBits(dest_bits) orelse
3345 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3346 const operand_ty = f.typeOf(ty_op.operand);
3347 const scalar_ty = operand_ty.scalarType(zcu);
3348 const scalar_int_info = scalar_ty.intInfo(zcu);
3349
3350 const need_cast = dest_c_bits < 64;
3351 const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64;
3352 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
3353 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);
3423 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
3424 const ref_arg = lowersToBigInt(operand_scalar_ty, zcu);
33543425
33553426 const w = &f.code.writer;
33563427 const local = try f.allocLocal(inst, inst_ty);
3428 if (is_big) try reap(f, inst, &.{ty_op.operand});
33573429 const v = try Vectorize.start(f, inst, w, operand_ty);
3358 try f.writeCValue(w, local, .other);
3359 try v.elem(f, w);
3360 try w.writeAll(" = ");
3361 if (need_cast) {
3362 try w.writeByte('(');
3363 try f.renderType(w, inst_scalar_ty);
3364 try w.writeByte(')');
3365 }
3366 if (need_lo) {
3367 try w.writeAll("zig_lo_");
3368 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3369 try w.writeByte('(');
3430 if (!ref_ret) {
3431 try f.writeCValue(w, local, .other);
3432 try v.elem(f, w);
3433 try w.writeAll(" = ");
33703434 }
3371 if (!need_mask) {
3372 try f.writeCValue(w, operand, .other);
3435 try w.writeAll("zig_");
3436 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
3437 try w.print("_{s}_", .{operation});
3438 try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty);
3439 try w.writeByte('(');
3440 if (ref_ret) {
3441 try w.writeByte('&');
3442 try f.writeCValue(w, local, .other);
33733443 try v.elem(f, w);
3374 } else switch (dest_int_info.signedness) {
3375 .unsigned => {
3376 try w.writeAll("zig_and_");
3377 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3378 try w.writeByte('(');
3379 try f.writeCValue(w, operand, .other);
3380 try v.elem(f, w);
3381 try w.print(", {f})", .{
3382 try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)),
3383 });
3384 },
3385 .signed => {
3386 const c_bits = toCIntBits(scalar_int_info.bits) orelse
3387 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3388 const shift_val = try pt.intValue(.u8, c_bits - dest_bits);
3389
3390 try w.writeAll("zig_shr_");
3391 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3392 if (c_bits == 128) {
3393 try w.print("(zig_bitCast_i{d}(", .{c_bits});
3394 } else {
3395 try w.print("((int{d}_t)", .{c_bits});
3396 }
3397 try w.print("zig_shl_u{d}(", .{c_bits});
3398 if (c_bits == 128) {
3399 try w.print("zig_bitCast_u{d}(", .{c_bits});
3400 } else {
3401 try w.print("(uint{d}_t)", .{c_bits});
3402 }
3403 try f.writeCValue(w, operand, .other);
3404 try v.elem(f, w);
3405 if (c_bits == 128) try w.writeByte(')');
3406 try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
3407 if (c_bits == 128) try w.writeByte(')');
3408 try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
3409 },
3444 try w.writeAll(", ");
34103445 }
3411 if (need_lo) try w.writeByte(')');
3412 try w.writeByte(';');
3446 if (ref_arg) {
3447 try w.writeByte('&');
3448 switch (operand) {
3449 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
3450 else => try f.writeCValue(w, operand, .other),
3451 }
3452 } else try f.writeCValue(w, operand, .other);
3453 try v.elem(f, w);
3454 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, info);
3455 try f.dg.renderBuiltinInfo(w, operand_scalar_ty, .none);
3456 try w.writeAll(");");
34133457 try f.newline();
34143458 try v.end(f, inst, w);
3459
34153460 return local;
34163461}
34173462
......@@ -3525,39 +3570,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
35253570 const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
35263571 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
35273572
3573 const lhs_ty = f.typeOf(bin_op.lhs);
3574 const rhs_ty = f.typeOf(bin_op.rhs);
3575 const is_big = lowersToBigInt(lhs_ty, zcu);
3576
35283577 const lhs = try f.resolveInst(bin_op.lhs);
35293578 const rhs = try f.resolveInst(bin_op.rhs);
3530 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3579 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
35313580
3532 const inst_ty = f.typeOfIndex(inst);
3533 const operand_ty = f.typeOf(bin_op.lhs);
3534 const scalar_ty = operand_ty.scalarType(zcu);
3581 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
3582 const rhs_scalar_ty = rhs_ty.scalarType(zcu);
35353583
3536 const ref_arg = lowersToBigInt(scalar_ty, zcu);
3584 const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu);
3585 const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu);
35373586
35383587 const w = &f.code.writer;
3539 const local = try f.allocLocal(inst, inst_ty);
3540 const v = try Vectorize.start(f, inst, w, operand_ty);
3588 const local = try f.allocLocal(inst, f.typeOfIndex(inst));
3589 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3590 const v = try Vectorize.start(f, inst, w, lhs_ty);
35413591 try f.writeCValueMember(w, local, .{ .field = 1 });
35423592 try v.elem(f, w);
3543 try w.writeAll(" = zig_");
3593 try w.writeAll(" = ");
3594 try w.writeAll("zig_");
35443595 try w.writeAll(operation);
35453596 try w.writeAll("o_");
3546 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3597 try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty);
35473598 try w.writeByte('(');
35483599
35493600 // '&dest', possibly preceded by a cast
3550 switch (zcu.intern_pool.indexToKey(scalar_ty.toIntern())) {
3601 switch (zcu.intern_pool.indexToKey(lhs_scalar_ty.toIntern())) {
35513602 .int_type => {}, // we already have a '[u]intX_t *'
35523603 .simple_type => {
35533604 // '&dest' will be something like a 'uintptr_t *', which might be a different C type to
35543605 // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a
35553606 // cast on the *operands* because they are passed by value (except for big integers,
35563607 // where this issue doesn't exist because no "simple" int type needs bigint repr).
3557 try w.print("({s}int{d}_t *)", .{
3558 if (scalar_ty.isUnsignedInt(zcu)) "u" else "",
3559 scalar_ty.abiSize(zcu) * 8,
3560 });
3608 const inst_int_info = lhs_scalar_ty.intInfo(zcu);
3609 try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) {
3610 .signed => "",
3611 .unsigned => "u",
3612 }, inst_int_info.bits });
35613613 },
35623614 else => unreachable,
35633615 }
......@@ -3566,14 +3618,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
35663618 try v.elem(f, w);
35673619
35683620 try w.writeAll(", ");
3569 if (ref_arg) try w.writeByte('&');
3570 try f.writeCValue(w, lhs, .other);
3621 if (ref_lhs) {
3622 try w.writeByte('&');
3623 switch (lhs) {
3624 .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val),
3625 else => try f.writeCValue(w, lhs, .other),
3626 }
3627 } else try f.writeCValue(w, lhs, .other);
35713628 try v.elem(f, w);
35723629 try w.writeAll(", ");
3573 if (ref_arg) try w.writeByte('&');
3574 try f.writeCValue(w, rhs, .other);
3575 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
3576 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
3630 if (ref_rhs) {
3631 try w.writeByte('&');
3632 switch (rhs) {
3633 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
3634 else => try f.writeCValue(w, rhs, .other),
3635 }
3636 } else try f.writeCValue(w, rhs, .other);
3637 try v.elem(f, w);
3638 try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info);
35773639 try w.writeAll(");");
35783640 try f.newline();
35793641 try v.end(f, inst, w);
......@@ -3622,8 +3684,18 @@ fn airBinOp(
36223684 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
36233685 const operand_ty = f.typeOf(bin_op.lhs);
36243686 const scalar_ty = operand_ty.scalarType(zcu);
3625 if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat())
3626 return try airBinBuiltinCall(f, inst, operation, info);
3687
3688 builtin: {
3689 if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) {
3690 .void => unreachable,
3691 .small => |int| switch (int) {
3692 else => break :builtin,
3693 .zig_u128, .zig_i128 => {},
3694 },
3695 .big => {},
3696 } else if (!scalar_ty.isRuntimeFloat()) break :builtin;
3697 return airBinBuiltinCall(f, inst, operation, info);
3698 }
36273699
36283700 const lhs = try f.resolveInst(bin_op.lhs);
36293701 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3662,19 +3734,21 @@ fn airCmpOp(
36623734 const lhs_ty = f.typeOf(data.lhs);
36633735 const scalar_ty = lhs_ty.scalarType(zcu);
36643736
3665 if (scalar_ty.isInt(zcu)) {
3666 const scalar_bits = scalar_ty.bitSize(zcu);
3667 if (scalar_bits > 64) return airCmpBuiltinCall(
3668 f,
3669 inst,
3670 data,
3671 operator,
3672 .cmp,
3673 if (scalar_bits > 128) .bits else .none,
3674 );
3737 builtin: {
3738 if (scalar_ty.isInt(zcu)) {
3739 switch (CType.classifyInt(scalar_ty, zcu)) {
3740 .void => unreachable,
3741 .small => |int| switch (int) {
3742 else => break :builtin,
3743 .zig_u128, .zig_i128 => {},
3744 },
3745 .big => {},
3746 }
3747 return airCmpBuiltinCall(f, inst, data, operator, .cmp, .none);
3748 }
3749 if (scalar_ty.isRuntimeFloat())
3750 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
36753751 }
3676 if (scalar_ty.isRuntimeFloat())
3677 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
36783752
36793753 const inst_ty = f.typeOfIndex(inst);
36803754 const lhs = try f.resolveInst(data.lhs);
......@@ -3716,21 +3790,23 @@ fn airEquality(
37163790 const pt = f.dg.pt;
37173791 const zcu = pt.zcu;
37183792 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
3719
37203793 const operand_ty = f.typeOf(bin_op.lhs);
3721 if (operand_ty.isAbiInt(zcu)) {
3722 const operand_bits = operand_ty.bitSize(zcu);
3723 if (operand_bits > 64) return airCmpBuiltinCall(
3724 f,
3725 inst,
3726 bin_op,
3727 operator,
3728 .cmp,
3729 if (operand_bits > 128) .bits else .none,
3730 );
3794
3795 builtin: {
3796 if (operand_ty.isAbiInt(zcu)) {
3797 switch (CType.classifyInt(operand_ty, zcu)) {
3798 .void => unreachable,
3799 .small => |int| switch (int) {
3800 else => break :builtin,
3801 .zig_u128, .zig_i128 => {},
3802 },
3803 .big => {},
3804 }
3805 return airCmpBuiltinCall(f, inst, bin_op, operator, .cmp, .none);
3806 }
3807 if (operand_ty.isRuntimeFloat())
3808 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
37313809 }
3732 if (operand_ty.isRuntimeFloat())
3733 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
37343810
37353811 const lhs = try f.resolveInst(bin_op.lhs);
37363812 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3809,7 +3885,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
38093885 try f.writeCValue(w, local, .other);
38103886 try w.writeAll(" = ");
38113887 try f.writeCValue(w, operand, .other);
3812 try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);");
3888 try w.writeAll(" <= sizeof(zig_errorName) / sizeof(*zig_errorName);");
38133889 try f.newline();
38143890 return local;
38153891}
......@@ -3862,8 +3938,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
38623938 const inst_ty = f.typeOfIndex(inst);
38633939 const inst_scalar_ty = inst_ty.scalarType(zcu);
38643940
3865 if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat())
3866 return try airBinBuiltinCall(f, inst, operation, .none);
3941 builtin: {
3942 if (inst_scalar_ty.isInt(zcu)) switch (CType.classifyInt(inst_scalar_ty, zcu)) {
3943 .void => unreachable,
3944 .small => |int| switch (int) {
3945 else => break :builtin,
3946 .zig_u128, .zig_i128 => {},
3947 },
3948 .big => {},
3949 } else if (!inst_scalar_ty.isRuntimeFloat()) break :builtin;
3950 return airBinBuiltinCall(f, inst, operation, .none);
3951 }
38673952
38683953 const lhs = try f.resolveInst(bin_op.lhs);
38693954 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3979,10 +4064,7 @@ fn airCall(
39794064 try w.writeAll("(void)");
39804065 break :result .none;
39814066 } else {
3982 const local = try f.allocAlignedLocal(inst, .{
3983 .type = ret_ty,
3984 .alignment = .none,
3985 });
4067 const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty });
39864068 try f.writeCValue(w, local, .other);
39874069 try w.writeAll(" = ");
39884070 break :result local;
......@@ -4058,16 +4140,7 @@ fn airCall(
40584140fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
40594141 const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt;
40604142 const w = &f.code.writer;
4061 // TODO re-evaluate whether to emit these or not. If we naively emit
4062 // these directives, the output file will report bogus line numbers because
4063 // every newline after the #line directive adds one to the line.
4064 // We also don't print the filename yet, so the output is strictly unhelpful.
4065 // If we wanted to go this route, we would need to go all the way and not output
4066 // newlines until the next dbg_stmt occurs.
4067 // Perhaps an additional compilation option is in order?
4068 //try w.print("#line {d}", .{dbg_stmt.line + 1});
4069 //try f.newline();
4070 try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
4143 try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
40714144 try f.newline();
40724145 return .none;
40734146}
......@@ -4433,12 +4506,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
44334506 const operand_scalar_ty = operand_ty.scalarType(zcu);
44344507 const dest_scalar_ty = dest_ty.scalarType(zcu);
44354508
4436 // Some cases are handled with a simple cast:
4437 // * float -> float
4438 // * bool -> int
44394509 if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or
44404510 (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu)))
44414511 {
4512 // Some cases are handled with a simple cast:
4513 // * float -> float
4514 // * bool -> int
44424515 try f.writeCValue(w, dest_local, .other);
44434516 try v.elem(f, w);
44444517 try w.writeAll(" = (");
......@@ -4458,85 +4531,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
44584531 try v.elem(f, w);
44594532 try w.writeAll(" != 0;");
44604533 try f.newline();
4461 } else if (dest_scalar_ty.isRuntimeFloat()) {
4462 // For int->float, just do a memcpy.
4463 assert(operand_scalar_ty.isAbiInt(zcu));
4464 try w.writeAll("memcpy(&");
4465 try f.writeCValue(w, dest_local, .other);
4466 try v.elem(f, w);
4467 try w.writeAll(", &");
4468 switch (operand) {
4469 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
4470 else => try f.writeCValue(w, operand, .other),
4471 }
4472 try v.elem(f, w);
4473 try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))});
4474 try f.newline();
44754534 } else {
4476 // The only remaining possibility is that the result is an integer. We will need to use
4477 // `zig_wrap_*` to correct the "padding" bits after we populate the value bits.
4478 assert(dest_scalar_ty.isAbiInt(zcu));
44794535 assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu));
4536 assert(dest_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isAbiInt(zcu));
44804537
4481 // memcpy the value...
4482 try w.writeAll("memcpy(&");
4483 try f.writeCValue(w, dest_local, .other);
4484 try v.elem(f, w);
4485 try w.writeAll(", &");
4486 switch (operand) {
4487 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
4488 else => try f.writeCValue(w, operand, .other),
4538 const ref_ret = lowersToBigInt(dest_scalar_ty, zcu);
4539 const ref_arg = lowersToBigInt(operand_scalar_ty, zcu);
4540
4541 if (!ref_ret) {
4542 try f.writeCValue(w, dest_local, .other);
4543 try v.elem(f, w);
4544 try w.writeAll(" = ");
44894545 }
4546 try w.writeAll("zig_");
4547 try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty);
4548 try w.writeAll("_bitCast_");
4549 try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty);
4550 try w.writeByte('(');
4551 if (ref_ret) {
4552 try w.writeByte('&');
4553 try f.writeCValue(w, dest_local, .other);
4554 try v.elem(f, w);
4555 try w.writeAll(", ");
4556 }
4557 if (ref_arg) {
4558 try w.writeByte('&');
4559 switch (operand) {
4560 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
4561 else => try f.writeCValue(w, operand, .other),
4562 }
4563 } else try f.writeCValue(w, operand, .other);
44904564 try v.elem(f, w);
4491 try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))});
4565 try f.dg.renderBuiltinInfo(
4566 w,
4567 dest_scalar_ty,
4568 if (operand_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isRuntimeFloat()) .none else .bits,
4569 );
4570 try w.writeAll(");");
44924571 try f.newline();
4493
4494 // ...and ensure padding bits have the correct value.
4495 switch (CType.classifyInt(dest_scalar_ty, zcu)) {
4496 .void => unreachable, // opv
4497 .small => {
4498 try f.writeCValue(w, dest_local, .other);
4499 try v.elem(f, w);
4500 try w.writeAll(" = zig_wrap_");
4501 try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty);
4502 try w.writeByte('(');
4503 try f.writeCValue(w, dest_local, .other);
4504 try v.elem(f, w);
4505 try f.dg.renderBuiltinInfo(w, dest_scalar_ty, .bits);
4506 try w.writeAll(");");
4507 try f.newline();
4508 },
4509 .big => |big| {
4510 const dest_info = dest_scalar_ty.intInfo(zcu);
4511 const padding_index: u16 = switch (f.dg.mod.resolved_target.result.cpu.arch.endian()) {
4512 .little => big.limbs_len - 1,
4513 .big => 0,
4514 };
4515 const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1;
4516 if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) {
4517 try f.writeCValue(w, dest_local, .other);
4518 try v.elem(f, w);
4519 try w.print(".limbs[{d}] = zig_wrap_{c}{d}(", .{
4520 padding_index,
4521 signAbbrev(dest_info.signedness),
4522 big.limb_size.bits(),
4523 });
4524 try f.writeCValue(w, dest_local, .other);
4525 try v.elem(f, w);
4526 try w.print(".limbs[{d}], {d});", .{ padding_index, wrap_bits });
4527 } else {
4528 try f.writeCValue(w, dest_local, .other);
4529 try v.elem(f, w);
4530 try w.print(".limbs[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{
4531 padding_index,
4532 });
4533 try f.writeCValue(w, dest_local, .other);
4534 try v.elem(f, w);
4535 try w.print(".limbs[{d}]), {d}));", .{ padding_index, wrap_bits });
4536 try f.newline();
4537 }
4538 },
4539 }
45404572 }
45414573
45424574 try v.end(f, inst, w);
......@@ -4906,11 +4938,9 @@ fn lowerSwitchCmp(
49064938
49074939fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
49084940 const dg = f.dg;
4909 const target = &dg.mod.resolved_target.result;
49104941 return switch (constraint[0]) {
49114942 '{' => true,
4912 'i', 'r' => false,
4913 'I' => !target.cpu.arch.isArm(),
4943 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false,
49144944 else => switch (value) {
49154945 .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) {
49164946 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
......@@ -4937,10 +4967,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49374967 const w = &f.code.writer;
49384968 const inst_ty = f.typeOfIndex(inst);
49394969 const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: {
4940 const inst_local = try f.allocLocalValue(.{
4941 .type = inst_ty,
4942 .alignment = .none,
4943 });
4970 const inst_local = try f.allocLocalValue(.{ .type = inst_ty });
49444971 if (f.wantSafety()) {
49454972 try f.writeCValue(w, inst_local, .other);
49464973 try w.writeAll(" = ");
......@@ -4967,10 +4994,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49674994 if (is_reg) {
49684995 const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu);
49694996 try w.writeAll("register ");
4970 const output_local = try f.allocLocalValue(.{
4971 .type = output_ty,
4972 .alignment = .none,
4973 });
4997 const output_local = try f.allocLocalValue(.{ .type = output_ty });
49744998 try f.allocs.put(gpa, output_local.new_local, false);
49754999 try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none);
49765000 try w.writeAll(" __asm(\"");
......@@ -5000,10 +5024,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
50005024 if (asmInputNeedsLocal(f, constraint, input_val)) {
50015025 const input_ty = f.typeOf(input.operand);
50025026 if (is_reg) try w.writeAll("register ");
5003 const input_local = try f.allocLocalValue(.{
5004 .type = input_ty,
5005 .alignment = .none,
5006 });
5027 const input_local = try f.allocLocalValue(.{ .type = input_ty });
50075028 try f.allocs.put(gpa, input_local.new_local, false);
50085029 // Do not render the declaration as `const` qualified if we're generating an
50095030 // explicit `register` local, as GCC will ignore the constraint completely.
......@@ -5853,28 +5874,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
58535874 else
58545875 unreachable;
58555876
5877 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
5878 const ref_operand = lowersToBigInt(scalar_ty, zcu);
5879
58565880 const w = &f.code.writer;
58575881 const local = try f.allocLocal(inst, inst_ty);
58585882 const v = try Vectorize.start(f, inst, w, operand_ty);
5859 try f.writeCValue(w, local, .other);
5860 try v.elem(f, w);
5861 try w.writeAll(" = ");
5883 if (ref_ret) {
5884 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5885 if (inst_int_info.bits <= 128) {
5886 try w.writeAll("zig_");
5887 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
5888 try w.print("_intCast_{c}{d}", .{
5889 @as(u8, switch (inst_int_info.signedness) {
5890 .signed => 'i',
5891 .unsigned => 'u',
5892 }),
5893 std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)),
5894 });
5895 try w.writeAll("(&");
5896 try f.writeCValue(w, local, .other);
5897 try v.elem(f, w);
5898 try w.writeAll(", ");
5899 }
5900 } else {
5901 try f.writeCValue(w, local, .other);
5902 try v.elem(f, w);
5903 try w.writeAll(" = ");
5904 }
58625905 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
5863 try w.writeAll("zig_wrap_");
5864 try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
5865 try w.writeByte('(');
5906 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5907 if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{
5908 @as(u8, switch (inst_int_info.signedness) {
5909 .signed => 'i',
5910 .unsigned => 'u',
5911 }),
5912 std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)),
5913 });
58665914 }
58675915 try w.writeAll("zig_");
58685916 try w.writeAll(operation);
58695917 try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));
58705918 try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));
58715919 try w.writeByte('(');
5872 try f.writeCValue(w, operand, .other);
5873 try v.elem(f, w);
5920 if (ref_ret) {
5921 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5922 if (inst_int_info.bits > 128) {
5923 try w.writeByte('&');
5924 try f.writeCValue(w, local, .other);
5925 try v.elem(f, w);
5926 try w.writeAll(", ");
5927 }
5928 }
5929 if (ref_operand) {
5930 const operand_int_info = scalar_ty.intInfo(zcu);
5931 if (operand_int_info.bits <= 128) {
5932 try w.print("zig_{c}{d}_intCast_", .{
5933 @as(u8, switch (operand_int_info.signedness) {
5934 .signed => 'i',
5935 .unsigned => 'u',
5936 }),
5937 std.math.ceilPowerOfTwoAssert(u16, @max(operand_int_info.bits, 32)),
5938 });
5939 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
5940 try w.writeAll("(&");
5941 switch (operand) {
5942 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
5943 else => try f.writeCValue(w, operand, .other),
5944 }
5945 try v.elem(f, w);
5946 try f.dg.renderBuiltinInfo(w, scalar_ty, .none);
5947 try w.writeByte(')');
5948 } else {
5949 try w.writeByte('&');
5950 switch (operand) {
5951 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
5952 else => try f.writeCValue(w, operand, .other),
5953 }
5954 try v.elem(f, w);
5955 try w.print(", {f}", .{fmtUnsignedIntLiteralSmall(
5956 target,
5957 .uint16_t,
5958 operand_int_info.bits,
5959 false,
5960 10,
5961 .lower,
5962 )});
5963 }
5964 } else {
5965 try f.writeCValue(w, operand, .other);
5966 try v.elem(f, w);
5967 }
5968 if (ref_ret) {
5969 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5970 if (inst_int_info.bits > 128) try w.print(", {f}", .{fmtUnsignedIntLiteralSmall(
5971 target,
5972 .uint16_t,
5973 inst_int_info.bits,
5974 false,
5975 10,
5976 .lower,
5977 )});
5978 }
58745979 try w.writeByte(')');
58755980 if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
5876 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits);
5877 try w.writeByte(')');
5981 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5982 if (inst_int_info.bits <= 128) {
5983 try w.print(", {f}", .{
5984 try f.dg.fmtIntLiteralDec(try pt.intValue(.u8, inst_int_info.bits), .other),
5985 });
5986 try w.writeByte(')');
5987 }
5988 }
5989 if (ref_ret) {
5990 const inst_int_info = inst_scalar_ty.intInfo(zcu);
5991 if (inst_int_info.bits <= 128) {
5992 try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .none);
5993 try w.writeByte(')');
5994 }
58785995 }
58795996 try w.writeByte(';');
58805997 try f.newline();
......@@ -5893,18 +6010,21 @@ fn airUnBuiltinCall(
58936010 const pt = f.dg.pt;
58946011 const zcu = pt.zcu;
58956012
5896 const operand = try f.resolveInst(operand_ref);
5897 try reap(f, inst, &.{operand_ref});
58986013 const inst_ty = f.typeOfIndex(inst);
58996014 const inst_scalar_ty = inst_ty.scalarType(zcu);
59006015 const operand_ty = f.typeOf(operand_ref);
59016016 const scalar_ty = operand_ty.scalarType(zcu);
6017 const is_big = lowersToBigInt(operand_ty, zcu);
6018
6019 const operand = try f.resolveInst(operand_ref);
6020 if (!is_big) try reap(f, inst, &.{operand_ref});
59026021
59036022 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
59046023 const ref_arg = lowersToBigInt(scalar_ty, zcu);
59056024
59066025 const w = &f.code.writer;
59076026 const local = try f.allocLocal(inst, inst_ty);
6027 if (is_big) try reap(f, inst, &.{operand_ref});
59086028 const v = try Vectorize.start(f, inst, w, operand_ty);
59096029 if (!ref_ret) {
59106030 try f.writeCValue(w, local, .other);
......@@ -5920,8 +6040,13 @@ fn airUnBuiltinCall(
59206040 try v.elem(f, w);
59216041 try w.writeAll(", ");
59226042 }
5923 if (ref_arg) try w.writeByte('&');
5924 try f.writeCValue(w, operand, .other);
6043 if (ref_arg) {
6044 try w.writeByte('&');
6045 switch (operand) {
6046 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6047 else => try f.writeCValue(w, operand, .other),
6048 }
6049 } else try f.writeCValue(w, operand, .other);
59256050 try v.elem(f, w);
59266051 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
59276052 try w.writeAll(");");
......@@ -5941,8 +6066,9 @@ fn airBinBuiltinCall(
59416066 const zcu = pt.zcu;
59426067 const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op;
59436068
5944 const operand_ty = f.typeOf(bin_op.lhs);
5945 const is_big = lowersToBigInt(operand_ty, zcu);
6069 const lhs_ty = f.typeOf(bin_op.lhs);
6070 const rhs_ty = f.typeOf(bin_op.rhs);
6071 const is_big = lowersToBigInt(lhs_ty, zcu);
59466072
59476073 const lhs = try f.resolveInst(bin_op.lhs);
59486074 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -5950,22 +6076,31 @@ fn airBinBuiltinCall(
59506076
59516077 const inst_ty = f.typeOfIndex(inst);
59526078 const inst_scalar_ty = inst_ty.scalarType(zcu);
5953 const scalar_ty = operand_ty.scalarType(zcu);
6079 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
6080 const rhs_scalar_ty = rhs_ty.scalarType(zcu);
59546081
59556082 const ref_ret = lowersToBigInt(inst_scalar_ty, zcu);
5956 const ref_arg = lowersToBigInt(scalar_ty, zcu);
6083 const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu);
6084 const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu);
59576085
59586086 const w = &f.code.writer;
59596087 const local = try f.allocLocal(inst, inst_ty);
59606088 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
5961 const v = try Vectorize.start(f, inst, w, operand_ty);
6089 const v = try Vectorize.start(f, inst, w, lhs_ty);
59626090 if (!ref_ret) {
59636091 try f.writeCValue(w, local, .other);
59646092 try v.elem(f, w);
59656093 try w.writeAll(" = ");
59666094 }
59676095 try w.print("zig_{s}_", .{operation});
5968 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
6096 try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty);
6097 switch (info) {
6098 .bits, .none, .big_temp_bits => {},
6099 .bits_none => {
6100 try w.writeByte('_');
6101 try f.dg.renderTypeForBuiltinFnName(w, rhs_scalar_ty);
6102 },
6103 }
59696104 try w.writeByte('(');
59706105 if (ref_ret) {
59716106 try w.writeByte('&');
......@@ -5973,15 +6108,45 @@ fn airBinBuiltinCall(
59736108 try v.elem(f, w);
59746109 try w.writeAll(", ");
59756110 }
5976 if (ref_arg) try w.writeByte('&');
5977 try f.writeCValue(w, lhs, .other);
6111 if (ref_lhs) {
6112 try w.writeByte('&');
6113 switch (lhs) {
6114 .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val),
6115 else => try f.writeCValue(w, lhs, .other),
6116 }
6117 } else try f.writeCValue(w, lhs, .other);
59786118 try v.elem(f, w);
59796119 try w.writeAll(", ");
5980 if (ref_arg) try w.writeByte('&');
5981 try f.writeCValue(w, rhs, .other);
5982 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
5983 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
5984 try w.writeAll(");\n");
6120 if (ref_rhs) {
6121 try w.writeByte('&');
6122 switch (rhs) {
6123 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
6124 else => try f.writeCValue(w, rhs, .other),
6125 }
6126 } else try f.writeCValue(w, rhs, .other);
6127 try v.elem(f, w);
6128 try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info: switch (info) {
6129 .none => .none,
6130 .bits, .bits_none => .bits,
6131 .big_temp_bits => {
6132 if (lowersToBigInt(lhs_scalar_ty, zcu)) {
6133 const temp_local = try f.allocAlignedLocal(inst, .{
6134 .type = lhs_scalar_ty,
6135 .array_len = 2,
6136 });
6137 try w.writeAll(", &");
6138 try f.writeCValue(w, temp_local, .other);
6139 try freeLocal(f, inst, temp_local.new_local, null);
6140 }
6141 break :info .none;
6142 },
6143 });
6144 switch (info) {
6145 .none, .bits, .big_temp_bits => {},
6146 .bits_none => try f.dg.renderBuiltinInfo(w, rhs_scalar_ty, .none),
6147 }
6148 try w.writeAll(");");
6149 try f.newline();
59856150 try v.end(f, inst, w);
59866151
59876152 return local;
......@@ -6029,12 +6194,22 @@ fn airCmpBuiltinCall(
60296194 try v.elem(f, w);
60306195 try w.writeAll(", ");
60316196 }
6032 if (ref_arg) try w.writeByte('&');
6033 try f.writeCValue(w, lhs, .other);
6197 if (ref_arg) {
6198 try w.writeByte('&');
6199 switch (lhs) {
6200 .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val),
6201 else => try f.writeCValue(w, lhs, .other),
6202 }
6203 } else try f.writeCValue(w, lhs, .other);
60346204 try v.elem(f, w);
60356205 try w.writeAll(", ");
6036 if (ref_arg) try w.writeByte('&');
6037 try f.writeCValue(w, rhs, .other);
6206 if (ref_arg) {
6207 try w.writeByte('&');
6208 switch (rhs) {
6209 .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val),
6210 else => try f.writeCValue(w, rhs, .other),
6211 }
6212 } else try f.writeCValue(w, rhs, .other);
60386213 try v.elem(f, w);
60396214 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
60406215 try w.writeByte(')');
......@@ -6595,7 +6770,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
65956770 },
65966771 .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other),
65976772 }
6598 try w.writeAll(";\n");
6773 try w.writeByte(';');
6774 try f.newline();
65996775 }
66006776
66016777 return local;
......@@ -6653,7 +6829,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66536829 const operand_ty = f.typeOf(reduce.operand);
66546830 const w = &f.code.writer;
66556831
6656 const use_operator = scalar_ty.bitSize(zcu) <= 64;
6832 const use_operator, const is_big = if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) {
6833 .void => unreachable,
6834 .small => |int| switch (int) {
6835 else => .{ true, false },
6836 .zig_u128, .zig_i128 => .{ false, false },
6837 },
6838 .big => .{ false, true },
6839 } else .{ false, false };
66576840 const op: union(enum) {
66586841 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
66596842 builtin: Func,
......@@ -6742,25 +6925,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
67426925 try f.newline();
67436926
67446927 const v = try Vectorize.start(f, inst, w, operand_ty);
6745 try f.writeCValue(w, accum, .other);
67466928 switch (op) {
67476929 .builtin => |func| {
6748 try w.print(" = zig_{s}_", .{func.operation});
6930 const prev_accum = if (is_big) prev_accum: {
6931 const prev_accum = try f.allocLocal(inst, scalar_ty);
6932 try f.writeCValue(w, prev_accum, .other);
6933 try w.writeAll(" = ");
6934 try f.writeCValue(w, accum, .other);
6935 try w.writeByte(';');
6936 try f.newline();
6937 break :prev_accum prev_accum;
6938 } else prev_accum: {
6939 try f.writeCValue(w, accum, .other);
6940 try w.writeAll(" = ");
6941 break :prev_accum accum;
6942 };
6943 try w.print("zig_{s}_", .{func.operation});
67496944 try f.dg.renderTypeForBuiltinFnName(w, scalar_ty);
67506945 try w.writeByte('(');
6751 try f.writeCValue(w, accum, .other);
6946 if (is_big) {
6947 try w.writeByte('&');
6948 switch (accum) {
6949 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6950 else => try f.writeCValue(w, accum, .other),
6951 }
6952 try w.writeAll(", &");
6953 switch (prev_accum) {
6954 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6955 else => try f.writeCValue(w, prev_accum, .other),
6956 }
6957 } else try f.writeCValue(w, prev_accum, .other);
67526958 try w.writeAll(", ");
6753 try f.writeCValue(w, operand, .other);
6959 if (is_big) {
6960 try w.writeByte('&');
6961 switch (operand) {
6962 .constant => |val| try f.dg.renderValueAsLvalue(w, val),
6963 else => try f.writeCValue(w, operand, .other),
6964 }
6965 } else try f.writeCValue(w, operand, .other);
67546966 try v.elem(f, w);
67556967 try f.dg.renderBuiltinInfo(w, scalar_ty, func.info);
67566968 try w.writeByte(')');
6969 if (is_big) try freeLocal(f, inst, prev_accum.new_local, null);
67576970 },
67586971 .infix => |ass| {
6972 try f.writeCValue(w, accum, .other);
67596973 try w.writeAll(ass);
67606974 try f.writeCValue(w, operand, .other);
67616975 try v.elem(f, w);
67626976 },
67636977 .ternary => |cmp| {
6978 try f.writeCValue(w, accum, .other);
67646979 try w.writeAll(" = ");
67656980 try f.writeCValue(w, accum, .other);
67666981 try w.writeAll(cmp);
......@@ -7097,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {
70977312 return w.writeAll(toMemoryOrder(order));
70987313}
70997314
7100fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 {
7101 if (zcu.getTarget().cCallingConvention()) |ccc| {
7102 if (cc.eql(ccc)) {
7103 return null;
7104 }
7105 }
7106 return switch (cc) {
7107 .auto, .naked => null,
7108
7109 .x86_16_cdecl => "cdecl",
7110 .x86_16_regparmcall => "regparmcall",
7111 .x86_64_sysv, .x86_sysv => "sysv_abi",
7112 .x86_64_win, .x86_win => "ms_abi",
7113 .x86_16_stdcall, .x86_stdcall => "stdcall",
7114 .x86_fastcall => "fastcall",
7115 .x86_thiscall => "thiscall",
7116
7117 .x86_vectorcall,
7118 .x86_64_vectorcall,
7119 => "vectorcall",
7120
7121 .x86_64_regcall_v3_sysv,
7122 .x86_64_regcall_v4_win,
7123 .x86_regcall_v3,
7124 .x86_regcall_v4_win,
7125 => "regcall",
7126
7127 .aarch64_vfabi => "aarch64_vector_pcs",
7128 .aarch64_vfabi_sve => "aarch64_sve_pcs",
7129
7130 .arm_aapcs => "pcs(\"aapcs\")",
7131 .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")",
7132
7133 .arc_interrupt => |opts| switch (opts.type) {
7134 inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")",
7135 },
7136
7137 .arm_interrupt => |opts| switch (opts.type) {
7138 .generic => "interrupt",
7139 .irq => "interrupt(\"IRQ\")",
7140 .fiq => "interrupt(\"FIQ\")",
7141 .swi => "interrupt(\"SWI\")",
7142 .abort => "interrupt(\"ABORT\")",
7143 .undef => "interrupt(\"UNDEF\")",
7144 },
7145
7146 .avr_signal => "signal",
7147
7148 .microblaze_interrupt => |opts| switch (opts.type) {
7149 .user => "save_volatiles",
7150 .regular => "interrupt_handler",
7151 .fast => "fast_interrupt",
7152 .breakpoint => "break_handler",
7153 },
7154
7155 .mips_interrupt,
7156 .mips64_interrupt,
7157 => |opts| switch (opts.mode) {
7158 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")",
7159 },
7160
7161 .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc",
7162
7163 .riscv32_interrupt,
7164 .riscv64_interrupt,
7165 => |opts| switch (opts.mode) {
7166 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")",
7167 },
7168
7169 .sh_renesas => "renesas",
7170 .sh_interrupt => |opts| switch (opts.save) {
7171 .fpscr => "trapa_handler", // Implies `interrupt_handler`.
7172 .high => "interrupt_handler, nosave_low_regs",
7173 .full => "interrupt_handler",
7174 .bank => "interrupt_handler, resbank",
7175 },
7176
7177 .m68k_rtd => "m68k_rtd",
7178
7179 .avr_interrupt,
7180 .csky_interrupt,
7181 .m68k_interrupt,
7182 .msp430_interrupt,
7183 .x86_16_interrupt,
7184 .x86_interrupt,
7185 .x86_64_interrupt,
7186 => "interrupt",
7187
7188 .ez80_tiflags,
7189 => "__tiflags__",
7190
7191 else => unreachable, // `Zcu.callconvSupported`
7192 };
7193}
7194
71957315fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {
71967316 return switch (order) {
71977317 .Xchg => "xchg",
......@@ -7224,17 +7344,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 {
72247344
72257345fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 {
72267346 return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) {
7347 0 => unreachable,
72277348 1...32 => "si",
72287349 33...64 => "di",
72297350 65...128 => "ti",
7230 else => unreachable,
7351 else => "ei",
72317352 } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {
7353 else => unreachable,
72327354 16 => "hf",
72337355 32 => "sf",
72347356 64 => "df",
72357357 80 => "xf",
7236 128 => "tf",
7237 else => unreachable,
7358 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf",
72387359 } else unreachable;
72397360}
72407361
......@@ -7390,10 +7511,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont
73907511 return .{ .data = .{ .str = str, .sentinel = sentinel } };
73917512}
73927513
7393fn undefPattern(comptime IntType: type) IntType {
7394 const int_info = @typeInfo(IntType).int;
7395 const UnsignedType = @Int(.unsigned, int_info.bits);
7396 return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
7514fn undefPattern(comptime Result: type) Result {
7515 return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3));
73977516}
73987517
73997518const FormatIntLiteralContext = struct {
......@@ -7580,11 +7699,9 @@ const FormatSignedIntLiteralSmall = struct {
75807699 case: std.fmt.Case,
75817700 pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void {
75827701 const bits = data.int_cty.bits(data.target);
7583 const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1);
7584 const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1));
7585 if (data.val == max_int) {
7702 if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) {
75867703 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});
7587 } else if (data.val == min_int) {
7704 } else if (data.val == @as(i64, std.math.minInt(i64)) >> @intCast(64 - bits)) {
75887705 return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)});
75897706 }
75907707 if (data.val < 0) try w.writeByte('-');
......@@ -7596,7 +7713,7 @@ const FormatSignedIntLiteralSmall = struct {
75967713 16 => try w.writeAll("0x"),
75977714 else => unreachable,
75987715 }
7599 // This `@abs` is safe thanks to the `min_int` case above.
7716 // This `@abs` is safe thanks to the min int check above.
76007717 try w.printInt(@abs(data.val), data.base, data.case, .{});
76017718 try w.writeAll(intLiteralSuffix(data.int_cty));
76027719 }
......@@ -7610,8 +7727,7 @@ const FormatUnsignedIntLiteralSmall = struct {
76107727 case: std.fmt.Case,
76117728 pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void {
76127729 const bits = data.int_cty.bits(data.target);
7613 const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits);
7614 if (data.val == max_int) {
7730 if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) {
76157731 return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)});
76167732 }
76177733 try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global));
......@@ -7735,6 +7851,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 {
77357851 };
77367852}
77377853
7854const F80Repr = packed struct {
7855 mantissa: u64,
7856 exponent: u16,
7857
7858 fn write(repr: F80Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void {
7859 try w.print("zig_{s}_repr_f80({f}, {f})", .{
7860 if (is_global) "init" else "make",
7861 fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.mantissa, is_global, 16, .lower),
7862 fmtUnsignedIntLiteralSmall(target, .uint16_t, repr.exponent, is_global, 16, .lower),
7863 });
7864 }
7865};
7866const F128Repr = packed struct {
7867 lo: u64,
7868 hi: u64,
7869
7870 fn write(repr: F128Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void {
7871 try w.print("zig_{s}_repr_f128({f}, {f})", .{
7872 if (is_global) "init" else "make",
7873 fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.hi, is_global, 16, .lower),
7874 fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.lo, is_global, 16, .lower),
7875 });
7876 }
7877};
7878
77387879const Materialize = struct {
77397880 local: CValue,
77407881
src/codegen/c/type.zig+198-23
......@@ -44,8 +44,175 @@ pub const CType = union(enum) {
4444 param_tys: []const CType,
4545 ret_ty: *const CType,
4646 varargs: bool,
47 cc: CallingConvention,
4748 },
4849
50 pub const CallingConvention = enum {
51 c,
52
53 cdecl,
54 regparmcall,
55 sysv_abi,
56 ms_abi,
57 stdcall,
58 fastcall,
59 thiscall,
60
61 vectorcall,
62
63 regcall,
64
65 aarch64_vector_pcs,
66 aarch64_sve_pcs,
67
68 @"pcs(\"aapcs\")",
69 @"pcs(\"aapcs-vfp\")",
70
71 @"interrupt(\"ilink1\")",
72 @"interrupt(\"ilink2\")",
73 @"interrupt(\"ilink\")",
74 @"interrupt(\"firq\")",
75
76 interrupt,
77 @"interrupt(\"IRQ\")",
78 @"interrupt(\"FIQ\")",
79 @"interrupt(\"SWI\")",
80 @"interrupt(\"ABORT\")",
81 @"interrupt(\"UNDEF\")",
82
83 signal,
84
85 save_volatiles,
86 interrupt_handler,
87 fast_interrupt,
88 break_handler,
89
90 @"interrupt(\"eic\")",
91 @"interrupt(\"sw0\")",
92 @"interrupt(\"sw1\")",
93 @"interrupt(\"hw0\")",
94 @"interrupt(\"hw1\")",
95 @"interrupt(\"hw2\")",
96 @"interrupt(\"hw3\")",
97 @"interrupt(\"hw4\")",
98 @"interrupt(\"hw5\")",
99
100 riscv_vector_cc,
101 @"interrupt(\"supervisor\")",
102 @"interrupt(\"machine\")",
103
104 renesas,
105 /// Implies `interrupt_handler`.
106 trapa_handler,
107 @"interrupt_handler, nosave_low_regs",
108 @"interrupt_handler, resbank",
109
110 m68k_rtd,
111
112 tiflags,
113
114 pub fn fromLang(cc: std.lang.CallingConvention, target: *const std.Target) CallingConvention {
115 if (target.cCallingConvention()) |ccc| {
116 if (cc.eql(ccc)) {
117 return .c;
118 }
119 }
120 return switch (cc) {
121 .auto, .naked => .c,
122
123 .x86_16_cdecl => .cdecl,
124 .x86_16_regparmcall => .regparmcall,
125 .x86_64_sysv, .x86_sysv => .sysv_abi,
126 .x86_64_win, .x86_win, .x86_mingw => .ms_abi,
127 .x86_16_stdcall, .x86_stdcall => .stdcall,
128 .x86_fastcall => .fastcall,
129 .x86_thiscall => .thiscall,
130
131 .x86_vectorcall,
132 .x86_64_vectorcall,
133 => .vectorcall,
134
135 .x86_64_regcall_v3_sysv,
136 .x86_64_regcall_v4_win,
137 .x86_regcall_v3,
138 .x86_regcall_v4_win,
139 => .regcall,
140
141 .aarch64_vfabi => .aarch64_vector_pcs,
142 .aarch64_vfabi_sve => .aarch64_sve_pcs,
143
144 .arm_aapcs => .@"pcs(\"aapcs\")",
145 .arm_aapcs_vfp => .@"pcs(\"aapcs-vfp\")",
146
147 .arc_interrupt => |opts| switch (opts.type) {
148 .ilink1 => .@"interrupt(\"ilink1\")",
149 .ilink2 => .@"interrupt(\"ilink2\")",
150 .ilink => .@"interrupt(\"ilink\")",
151 .firq => .@"interrupt(\"firq\")",
152 },
153
154 .arm_interrupt => |opts| switch (opts.type) {
155 .generic => .interrupt,
156 .irq => .@"interrupt(\"IRQ\")",
157 .fiq => .@"interrupt(\"FIQ\")",
158 .swi => .@"interrupt(\"SWI\")",
159 .abort => .@"interrupt(\"ABORT\")",
160 .undef => .@"interrupt(\"UNDEF\")",
161 },
162
163 .avr_signal => .signal,
164
165 .microblaze_interrupt => |opts| switch (opts.type) {
166 .user => .save_volatiles,
167 .regular => .interrupt_handler,
168 .fast => .fast_interrupt,
169 .breakpoint => .break_handler,
170 },
171
172 .mips_interrupt, .mips64_interrupt => |opts| switch (opts.mode) {
173 .eic => .@"interrupt(\"eic\")",
174 .sw0 => .@"interrupt(\"sw0\")",
175 .sw1 => .@"interrupt(\"sw1\")",
176 .hw0 => .@"interrupt(\"hw0\")",
177 .hw1 => .@"interrupt(\"hw1\")",
178 .hw2 => .@"interrupt(\"hw2\")",
179 .hw3 => .@"interrupt(\"hw3\")",
180 .hw4 => .@"interrupt(\"hw4\")",
181 .hw5 => .@"interrupt(\"hw5\")",
182 },
183
184 .riscv64_lp64_v, .riscv32_ilp32_v => .riscv_vector_cc,
185 .riscv32_interrupt, .riscv64_interrupt => |opts| switch (opts.mode) {
186 .supervisor => .@"interrupt(\"supervisor\")",
187 .machine => .@"interrupt(\"machine\")",
188 },
189
190 .sh_renesas => .renesas,
191 .sh_interrupt => |opts| switch (opts.save) {
192 .fpscr => .trapa_handler,
193 .high => .@"interrupt_handler, nosave_low_regs",
194 .full => .interrupt_handler,
195 .bank => .@"interrupt_handler, resbank",
196 },
197
198 .m68k_rtd => .m68k_rtd,
199
200 .avr_interrupt,
201 .csky_interrupt,
202 .m68k_interrupt,
203 .msp430_interrupt,
204 .x86_16_interrupt,
205 .x86_interrupt,
206 .x86_64_interrupt,
207 => .interrupt,
208
209 .ez80_tiflags => .tiflags,
210
211 else => unreachable, // `Zcu.callconvSupported`
212 };
213 }
214 };
215
49216 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears
50217 /// after the identifier in a declarator with this type. In this case, if this node is wrapped
51218 /// in a pointer type, we will need to add parentheses due to operator precedence.
......@@ -130,28 +297,28 @@ pub const CType = union(enum) {
130297 pub fn bits(int: Int, target: *const std.Target) u16 {
131298 return switch (int) {
132299 // zig fmt: off
133 .char => target.cTypeBitSize(.char),
134
135 .@"unsigned short" => target.cTypeBitSize(.ushort),
136 .@"unsigned int" => target.cTypeBitSize(.uint),
137 .@"unsigned long" => target.cTypeBitSize(.ulong),
138 .@"unsigned long long" => target.cTypeBitSize(.ulonglong),
139
140 .@"signed short" => target.cTypeBitSize(.short),
141 .@"signed int" => target.cTypeBitSize(.int),
142 .@"signed long" => target.cTypeBitSize(.long),
143 .@"signed long long" => target.cTypeBitSize(.longlong),
144
145 .uintptr_t, .intptr_t => target.ptrBitWidth(),
146
147 .uint8_t, .int8_t => 8,
148 .uint16_t, .int16_t => 16,
149 .uint24_t, .int24_t => 24,
150 .uint32_t, .int32_t => 32,
151 .uint48_t, .int48_t => 48,
152 .uint64_t, .int64_t => 64,
153 .zig_u128, .zig_i128 => 128,
154 // zig fmt: on
300 .char => target.cTypeBitSize(.char).?,
301
302 .@"unsigned short" => target.cTypeBitSize(.ushort).?,
303 .@"unsigned int" => target.cTypeBitSize(.uint).?,
304 .@"unsigned long" => target.cTypeBitSize(.ulong).?,
305 .@"unsigned long long" => target.cTypeBitSize(.ulonglong).?,
306
307 .@"signed short" => target.cTypeBitSize(.short).?,
308 .@"signed int" => target.cTypeBitSize(.int).?,
309 .@"signed long" => target.cTypeBitSize(.long).?,
310 .@"signed long long" => target.cTypeBitSize(.longlong).?,
311
312 .uintptr_t, .intptr_t => target.ptrBitWidth(),
313
314 .uint8_t, .int8_t => 8,
315 .uint16_t, .int16_t => 16,
316 .uint24_t, .int24_t => 24,
317 .uint32_t, .int32_t => 32,
318 .uint48_t, .int48_t => 48,
319 .uint64_t, .int64_t => 64,
320 .zig_u128, .zig_i128 => 128,
321 // zig fmt: on
155322 };
156323 }
157324 };
......@@ -376,6 +543,7 @@ pub const CType = union(enum) {
376543 .ret_ty = ret_cty_buf,
377544 .param_tys = param_cty_buf,
378545 .varargs = func_type.is_var_args,
546 .cc = .fromLang(func_type.cc, zcu.getTarget()),
379547 } };
380548 }
381549 try deps.addType(gpa, cur_ty, allow_incomplete);
......@@ -763,6 +931,13 @@ pub const CType = union(enum) {
763931 try w.writeByte('(');
764932 },
765933 }
934 switch (ptr.elem_ty.*) {
935 else => {},
936 .function => |function| switch (function.cc) {
937 .c => {},
938 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
939 },
940 }
766941 try w.writeByte('*');
767942 },
768943
......@@ -812,7 +987,7 @@ pub const CType = union(enum) {
812987 => {},
813988
814989 .pointer => |ptr| {
815 // Match opening paren "(" write `writeTypePrefix`.
990 // Match opening paren "(" in `writeTypePrefix`.
816991 switch (ptr.elem_ty.kind()) {
817992 .specifier, .pointer => {},
818993 .postfix_op => try w.writeByte(')'),
src/codegen/c/type/render_defs.zig+143-155
......@@ -21,16 +21,21 @@ pub fn defineAligned(
2121 if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
2222 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
2323 }
24 try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{
24 try w.print("{f}{f}{f};", .{
2525 cty.fmtDeclaratorPrefix(zcu),
2626 name_cty.fmtTypeName(zcu),
2727 cty.fmtDeclaratorSuffix(zcu),
28 });
29 if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{
2830 alignment.toByteUnits().?,
2931 ty.fmt(pt),
3032 });
33 try w.writeByte('\n');
3134}
3235/// Renders the definition of a big-int `struct`.
3336pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void {
37 const target = zcu.getTarget();
38 const bits = big.limb_size.bits() *| big.limbs_len;
3439 const name_cty: CType = .{ .bigint = .{
3540 .limb_size = big.limb_size,
3641 .limbs_len = big.limbs_len,
......@@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error
4146 .elem_ty = &limb_cty,
4247 .nonstring = limb_cty.isStringElem(),
4348 } };
44 try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{
49 try w.print("{f} {{ {f}limbs{f}; }};", .{
4550 name_cty.fmtTypeName(zcu),
4651 array_cty.fmtDeclaratorPrefix(zcu),
4752 array_cty.fmtDeclaratorSuffix(zcu),
48 big.limb_size.bits() * @as(u17, big.limbs_len),
4953 });
54 if (!zcu.comp.config.root_strip) try w.print(" /* u{d}, i{d} */", .{ bits, bits });
55 try w.writeByte('\n');
56 try writeStaticAssertCTypeLayout(
57 name_cty,
58 std.zig.target.intByteSize(target, bits),
59 .fromByteUnits(std.zig.target.intAlignment(target, bits)),
60 w,
61 zcu,
62 );
5063}
5164
5265/// Renders a forward declaration of the `struct` which represents an error union whose payload type
......@@ -81,27 +94,28 @@ pub fn errunionDefineComplete(
8194 if (payload_ty.hasRuntimeBits(zcu)) {
8295 const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu);
8396 try w.print(
84 \\{f} {{ /* anyerror!{f} */
97 \\{f} {{
8598 \\ {f}payload{f};
8699 \\ {f}error{f};
87100 \\}};
88 \\
89101 , .{
90102 name_cty.fmtTypeName(zcu),
91 payload_ty.fmt(pt),
92103 payload_cty.fmtDeclaratorPrefix(zcu),
93104 payload_cty.fmtDeclaratorSuffix(zcu),
94105 error_cty.fmtDeclaratorPrefix(zcu),
95106 error_cty.fmtDeclaratorSuffix(zcu),
96107 });
97108 } else {
98 try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{
109 try w.print("{f} {{ {f}error{f}; }};", .{
99110 name_cty.fmtTypeName(zcu),
100111 error_cty.fmtDeclaratorPrefix(zcu),
101112 error_cty.fmtDeclaratorSuffix(zcu),
102 payload_ty.fmt(pt),
103113 });
104114 }
115 if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{
116 payload_ty.fmt(pt),
117 });
118 try w.writeByte('\n');
105119}
106120
107121/// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that
......@@ -141,10 +155,13 @@ pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!vo
141155 },
142156 else => return,
143157 };
144 try w.print("typedef void {f}; /* {f} */\n", .{
158 try w.print("typedef void {f};", .{
145159 name_cty.fmtTypeName(zcu),
160 });
161 if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
146162 ty.fmt(pt),
147163 });
164 try w.writeByte('\n');
148165}
149166
150167/// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the
......@@ -163,13 +180,13 @@ pub fn defineComplete(
163180
164181 ty.assertHasLayout(zcu);
165182
166 switch (ty.zigTypeTag(zcu)) {
183 const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) {
167184 .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) {
168185 const name_cty: CType = .{ .@"fn" = ty };
169 try w.print("typedef void {f}; /* {f} */\n", .{
186 try w.print("typedef void {f};", .{
170187 name_cty.fmtTypeName(zcu),
171 ty.fmt(pt),
172188 });
189 break :check_cty null;
173190 } else {
174191 const ip = &zcu.intern_pool;
175192 const func_type = ip.indexToKey(ty.toIntern()).func_type;
......@@ -186,10 +203,12 @@ pub fn defineComplete(
186203 const name_cty: CType = .{ .@"fn" = ty };
187204 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);
188205
189 try w.print("typedef {f}{f}(", .{
190 ret_cty.fmtDeclaratorPrefix(zcu),
191 name_cty.fmtTypeName(zcu),
192 });
206 try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
207 switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) {
208 .c => {},
209 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
210 }
211 try w.print("{f}(", .{name_cty.fmtTypeName(zcu)});
193212 var any_params = false;
194213 for (func_type.param_types.get(ip)) |param_ty_ip| {
195214 const param_ty: Type = .fromInterned(param_ty_ip);
......@@ -205,88 +224,85 @@ pub fn defineComplete(
205224 } else if (!any_params) {
206225 try w.writeAll("void");
207226 }
208 try w.print("){f}; /* {f} */\n", .{
209 ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu),
210 ty.fmt(pt),
211 });
227 try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)});
228 break :check_cty null;
212229 },
213230 .@"enum" => {
214231 const name_cty: CType = .{ .@"enum" = ty };
215232 const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu);
216 try w.print("typedef {f}{f}{f}; /* {f} */\n", .{
233 try w.print("typedef {f}{f}{f};", .{
217234 cty.fmtDeclaratorPrefix(zcu),
218235 name_cty.fmtTypeName(zcu),
219236 cty.fmtDeclaratorSuffix(zcu),
220 ty.fmt(pt),
221237 });
238 break :check_cty null;
222239 },
223 .@"struct" => if (ty.isTuple(zcu)) {
224 try defineTuple(ty, deps, arena, w, pt);
225 } else switch (ty.containerLayout(zcu)) {
226 .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt),
240 .@"struct" => if (ty.isTuple(zcu))
241 if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return
242 else switch (ty.containerLayout(zcu)) {
243 .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return,
227244 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),
228245 },
229246 .@"union" => switch (ty.containerLayout(zcu)) {
230 .auto => try defineUnionAuto(ty, deps, arena, w, pt),
231 .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt),
247 .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return,
248 .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return,
232249 .@"packed" => try defineBitpack(ty, deps, arena, w, pt),
233250 },
234251 .pointer => if (ty.isSlice(zcu)) {
235252 const name_cty: CType = .{ .slice = ty };
236253 const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu);
237254 try w.print(
238 \\{f} {{ /* {f} */
255 \\{f} {{
239256 \\ {f}ptr{f};
240 \\ size_t len;
257 \\ uintptr_t len;
241258 \\}};
242 \\
243259 , .{
244260 name_cty.fmtTypeName(zcu),
245 ty.fmt(pt),
246261 ptr_cty.fmtDeclaratorPrefix(zcu),
247262 ptr_cty.fmtDeclaratorSuffix(zcu),
248263 });
249 // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess
250 // slices up, and they're all obviously the same layout.
251 },
264 break :check_cty switch (ty.toIntern()) {
265 .slice_const_u8_sentinel_0_type => name_cty,
266 else => null,
267 };
268 } else return,
252269 .optional => switch (CType.classifyOptional(ty, zcu)) {
253270 .error_set,
254271 .ptr_like,
255272 .slice_like,
256273 .npv_payload,
257 => {},
274 => return,
258275
259276 .opv_payload => {
260277 const name_cty: CType = .{ .opt = ty };
261 try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{
278 try w.print("{f} {{ bool is_null; }};", .{
262279 name_cty.fmtTypeName(zcu),
263 ty.fmt(pt),
264280 });
265 try writeStaticAssertLayout(ty, name_cty, w, zcu);
281 break :check_cty switch (ty.toIntern()) {
282 .optional_noreturn_type => name_cty,
283 else => null,
284 };
266285 },
267286
268287 .@"struct" => {
269288 const name_cty: CType = .{ .opt = ty };
270289 const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu);
271290 try w.print(
272 \\{f} {{ /* {f} */
291 \\{f} {{
273292 \\ {f}payload{f};
274293 \\ bool is_null;
275294 \\}};
276 \\
277295 , .{
278296 name_cty.fmtTypeName(zcu),
279 ty.fmt(pt),
280297 payload_cty.fmtDeclaratorPrefix(zcu),
281298 payload_cty.fmtDeclaratorSuffix(zcu),
282299 });
283 try writeStaticAssertLayout(ty, name_cty, w, zcu);
300 break :check_cty name_cty;
284301 },
285302 },
286303 .array => if (ty.hasRuntimeBits(zcu)) {
287 const elem_ty = ty.childType(zcu);
288304 const name_cty: CType = .{ .arr = ty };
289 const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu);
305 const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu);
290306 const array_cty: CType = .{ .array = .{
291307 .len = ty.arrayLenIncludingSentinel(zcu),
292308 .elem_ty = &elem_cty,
......@@ -296,43 +312,35 @@ pub fn defineComplete(
296312 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);
297313 },
298314 } };
299 if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) {
300 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
301 name_cty.fmtTypeName(zcu),
302 array_cty.fmtDeclaratorPrefix(zcu),
303 array_cty.fmtDeclaratorSuffix(zcu),
304 ty.fmt(pt),
305 });
306 } else {
307 try w.print("zig_packed({f} {{ zig_under_align({d}) {f}array{f}; }}); /* {f} */\n", .{
308 name_cty.fmtTypeName(zcu),
309 elem_ty.abiAlignment(zcu).toByteUnits().?,
310 array_cty.fmtDeclaratorPrefix(zcu),
311 array_cty.fmtDeclaratorSuffix(zcu),
312 ty.fmt(pt),
313 });
314 }
315 try writeStaticAssertLayout(ty, name_cty, w, zcu);
316 },
315 try w.print("{f} {{ {f}array{f}; }};", .{
316 name_cty.fmtTypeName(zcu),
317 array_cty.fmtDeclaratorPrefix(zcu),
318 array_cty.fmtDeclaratorSuffix(zcu),
319 });
320 break :check_cty name_cty;
321 } else return,
317322 .vector => if (ty.hasRuntimeBits(zcu)) {
318 const elem_ty = ty.childType(zcu);
319323 const name_cty: CType = .{ .vec = ty };
320 const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu);
324 const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu);
321325 const array_cty: CType = .{ .array = .{
322326 .len = ty.arrayLenIncludingSentinel(zcu),
323327 .elem_ty = &elem_cty,
324328 .nonstring = elem_cty.isStringElem(),
325329 } };
326 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
330 try w.print("{f} {{ {f}array{f}; }};", .{
327331 name_cty.fmtTypeName(zcu),
328332 array_cty.fmtDeclaratorPrefix(zcu),
329333 array_cty.fmtDeclaratorSuffix(zcu),
330 ty.fmt(pt),
331334 });
332 try writeStaticAssertLayout(ty, name_cty, w, zcu);
333 },
334 else => {},
335 }
335 break :check_cty name_cty;
336 } else return,
337 else => return,
338 };
339 if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
340 ty.fmt(pt),
341 });
342 try w.writeByte('\n');
343 if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu);
336344}
337345fn defineBitpack(
338346 ty: Type,
......@@ -340,16 +348,16 @@ fn defineBitpack(
340348 arena: Allocator,
341349 w: *Writer,
342350 pt: Zcu.PerThread,
343) (Allocator.Error || Writer.Error)!void {
351) (Allocator.Error || Writer.Error)!?CType {
344352 const zcu = pt.zcu;
345353 const name_cty: CType = .{ .bitpack = ty };
346354 const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu);
347 try w.print("typedef {f}{f}{f}; /* {f} */\n", .{
355 try w.print("typedef {f}{f}{f};", .{
348356 cty.fmtDeclaratorPrefix(zcu),
349357 name_cty.fmtTypeName(zcu),
350358 cty.fmtDeclaratorSuffix(zcu),
351 ty.fmt(pt),
352359 });
360 return null;
353361}
354362fn defineTuple(
355363 ty: Type,
......@@ -357,72 +365,54 @@ fn defineTuple(
357365 arena: Allocator,
358366 w: *Writer,
359367 pt: Zcu.PerThread,
360) (Allocator.Error || Writer.Error)!void {
368) (Allocator.Error || Writer.Error)!CType {
361369 const zcu = pt.zcu;
362 if (!ty.hasRuntimeBits(zcu)) return;
363370 const ip = &zcu.intern_pool;
364371 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;
365372
366 const tuple_align = ty.abiAlignment(zcu);
373 // Fields cannot be underaligned, because tuple fields cannot have specified alignments.
374 // However, overaligned fields are possible thanks to intermediate zero-bit fields.
367375
368 // If there are any underaligned fields, we need to byte-pack the tuple.
369 const pack: bool = pack: {
370 var offset: u64 = 0;
371 for (tuple.types.get(ip)) |field_ty_ip| {
372 const field_ty: Type = .fromInterned(field_ty_ip);
373 if (!field_ty.hasRuntimeBits(zcu)) continue;
374 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
375 const natural_offset = natural_align.forward(offset);
376 offset = field_ty.abiAlignment(zcu).forward(offset);
377 if (offset < natural_offset) break :pack true;
378 // Also pack if any field is more aligned than the tuple should be.
379 if (natural_align.compareStrict(.gt, tuple_align)) break :pack true;
380 offset += field_ty.abiSize(zcu);
381 }
382 break :pack false;
383 };
376 const tuple_align = ty.abiAlignment(zcu);
384377
385378 // If the alignment of other fields would not give the tuple sufficient alignment, we
386379 // need to align the first field (which does not affect its offset, because 0 is always
387380 // well-aligned) to indirectly specify the tuple alignment.
388 const overalign: bool = switch (pack) {
389 true => tuple_align.compareStrict(.gt, .@"1"),
390 false => for (tuple.types.get(ip)) |field_ty_ip| {
391 const field_ty: Type = .fromInterned(field_ty_ip);
392 if (!field_ty.hasRuntimeBits(zcu)) continue;
393 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
394 if (natural_align.compareStrict(.gte, tuple_align)) break false;
395 } else true,
396 };
381 const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| {
382 const field_ty: Type = .fromInterned(field_ty_ip);
383 if (!field_ty.hasRuntimeBits(zcu)) continue;
384 const natural_align = field_ty.abiAlignment(zcu);
385 if (natural_align.compareStrict(.gte, tuple_align)) break false;
386 } else true;
397387
398 if (pack) try w.writeAll("zig_packed(");
399388 const name_cty: CType = .{ .@"struct" = ty };
400 try w.print("{f} {{ /* {f} */\n", .{
389 try w.print("{f} {{\n", .{
401390 name_cty.fmtTypeName(zcu),
402 ty.fmt(pt),
403391 });
404392 var zig_offset: u64 = 0;
405393 var c_offset: u64 = 0;
406394 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {
407395 if (field_val_ip != .none) continue; // `comptime` field
408396 const field_ty: Type = .fromInterned(field_ty_ip);
409 zig_offset = field_ty.abiAlignment(zcu).forward(zig_offset);
397 const field_align = field_ty.abiAlignment(zcu);
398 zig_offset = field_align.forward(zig_offset);
410399 if (!field_ty.hasRuntimeBits(zcu)) continue;
411 if (!pack) c_offset = field_ty.defaultStructFieldAlignment(.auto, zcu).forward(c_offset);
400 c_offset = field_align.forward(c_offset);
412401 try w.writeByte(' ');
413402 if (zig_offset == 0 and overalign) {
414403 // This is the first field; specify its alignment to align the tuple.
415404 try writeFieldAlign(field_ty, tuple_align, w, zcu);
416 } else if (zig_offset > c_offset) {
417 // This field needs to be underaligned or overaligned compared to what its
418 // offset would otherwise be.
419 const need_align: Alignment = .minStrict(
420 tuple_align, // don't make the tuple more aligned than it should be
421 .fromLog2Units(@ctz(zig_offset)),
422 );
423 try writeFieldAlign(field_ty, need_align, w, zcu);
424 c_offset = need_align.forward(c_offset);
405 } else switch (zig_offset - c_offset) {
406 0 => {},
407 else => |need_bytes| {
408 // This field needs to be overaligned compared to what its offset would otherwise be.
409 const need_align: Alignment = .fromLog2Units(std.math.log2_int(u64, need_bytes) + 1);
410 assert(need_align.compareStrict(.lte, tuple_align));
411 try writeFieldAlign(field_ty, need_align, w, zcu);
412 c_offset = need_align.forward(c_offset);
413 },
425414 }
415 assert(c_offset == zig_offset);
426416 const field_cty: CType = try .lower(field_ty, deps, arena, zcu);
427417 try w.print("{f}f{d}{f};\n", .{
428418 field_cty.fmtDeclaratorPrefix(zcu),
......@@ -433,11 +423,8 @@ fn defineTuple(
433423 zig_offset += field_size;
434424 c_offset += field_size;
435425 }
436 try w.writeByte('}');
437 if (pack) try w.writeByte(')');
438 try w.writeAll(";\n");
439
440 try writeStaticAssertLayout(ty, name_cty, w, zcu);
426 try w.writeAll("};");
427 return name_cty;
441428}
442429fn defineStruct(
443430 ty: Type,
......@@ -445,9 +432,8 @@ fn defineStruct(
445432 arena: Allocator,
446433 w: *Writer,
447434 pt: Zcu.PerThread,
448) (Allocator.Error || Writer.Error)!void {
435) (Allocator.Error || Writer.Error)!CType {
449436 const zcu = pt.zcu;
450 if (!ty.hasRuntimeBits(zcu)) return;
451437 const ip = &zcu.intern_pool;
452438
453439 const struct_type = ip.loadStructType(ty.toIntern());
......@@ -459,7 +445,7 @@ fn defineStruct(
459445 while (it.next()) |field_index| {
460446 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
461447 if (!field_ty.hasRuntimeBits(zcu)) continue;
462 const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu);
448 const natural_align = field_ty.abiAlignment(zcu);
463449 const natural_offset = natural_align.forward(offset);
464450 const actual_offset = struct_type.field_offsets.get(ip)[field_index];
465451 if (actual_offset < natural_offset) break :pack true;
......@@ -480,7 +466,7 @@ fn defineStruct(
480466 while (it.next()) |field_index| {
481467 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
482468 if (!field_ty.hasRuntimeBits(zcu)) continue;
483 const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu);
469 const natural_align = field_ty.abiAlignment(zcu);
484470 if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false;
485471 }
486472 break :overalign true;
......@@ -489,16 +475,15 @@ fn defineStruct(
489475
490476 if (pack) try w.writeAll("zig_packed(");
491477 const name_cty: CType = .{ .@"struct" = ty };
492 try w.print("{f} {{ /* {f} */\n", .{
478 try w.print("{f} {{\n", .{
493479 name_cty.fmtTypeName(zcu),
494 ty.fmt(pt),
495480 });
496481 var it = struct_type.iterateRuntimeOrder(ip);
497482 var offset: u64 = 0;
498483 while (it.next()) |field_index| {
499484 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
500485 if (!field_ty.hasRuntimeBits(zcu)) continue;
501 const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu);
486 const natural_align = field_ty.abiAlignment(zcu);
502487 const natural_offset = switch (pack) {
503488 true => offset,
504489 false => natural_align.forward(offset),
......@@ -529,9 +514,8 @@ fn defineStruct(
529514 assert(struct_type.alignment.forward(offset) == struct_type.size);
530515 try w.writeByte('}');
531516 if (pack) try w.writeByte(')');
532 try w.writeAll(";\n");
533
534 try writeStaticAssertLayout(ty, name_cty, w, zcu);
517 try w.writeByte(';');
518 return name_cty;
535519}
536520fn defineUnionAuto(
537521 ty: Type,
......@@ -539,9 +523,8 @@ fn defineUnionAuto(
539523 arena: Allocator,
540524 w: *Writer,
541525 pt: Zcu.PerThread,
542) (Allocator.Error || Writer.Error)!void {
526) (Allocator.Error || Writer.Error)!CType {
543527 const zcu = pt.zcu;
544 if (!ty.hasRuntimeBits(zcu)) return;
545528 const ip = &zcu.intern_pool;
546529
547530 const union_type = ip.loadUnionType(ty.toIntern());
......@@ -553,7 +536,7 @@ fn defineUnionAuto(
553536 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
554537 const field_ty: Type = .fromInterned(field_ty_ip);
555538 if (!field_ty.hasRuntimeBits(zcu)) continue;
556 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
539 const natural_align = field_ty.abiAlignment(zcu);
557540 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
558541 // The tag will immediately follow the payload. This layout may put the tag in what would
559542 // otherwise be padding on the payload union, because if the most-aligned union field is not
......@@ -571,7 +554,7 @@ fn defineUnionAuto(
571554 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
572555 const field_ty: Type = .fromInterned(field_ty_ip);
573556 if (!field_ty.hasRuntimeBits(zcu)) continue;
574 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
557 const natural_align = field_ty.abiAlignment(zcu);
575558 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
576559 } else overalign: {
577560 if (union_type.has_runtime_tag) {
......@@ -585,9 +568,8 @@ fn defineUnionAuto(
585568 const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu);
586569
587570 const name_cty: CType = .{ .union_auto = ty };
588 try w.print("{f} {{ /* {f} */\n", .{
571 try w.print("{f} {{\n", .{
589572 name_cty.fmtTypeName(zcu),
590 ty.fmt(pt),
591573 });
592574 if (payload_has_bits) {
593575 try w.writeByte(' ');
......@@ -619,9 +601,8 @@ fn defineUnionAuto(
619601 tag_cty.fmtDeclaratorSuffix(zcu),
620602 });
621603 }
622 try w.writeAll("};\n");
623
624 try writeStaticAssertLayout(ty, name_cty, w, zcu);
604 try w.writeAll("};");
605 return name_cty;
625606}
626607fn defineUnionExtern(
627608 ty: Type,
......@@ -629,9 +610,8 @@ fn defineUnionExtern(
629610 arena: Allocator,
630611 w: *Writer,
631612 pt: Zcu.PerThread,
632) (Allocator.Error || Writer.Error)!void {
613) (Allocator.Error || Writer.Error)!CType {
633614 const zcu = pt.zcu;
634 if (!ty.hasRuntimeBits(zcu)) return;
635615 const ip = &zcu.intern_pool;
636616
637617 const union_type = ip.loadUnionType(ty.toIntern());
......@@ -642,7 +622,7 @@ fn defineUnionExtern(
642622 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
643623 const field_ty: Type = .fromInterned(field_ty_ip);
644624 if (!field_ty.hasRuntimeBits(zcu)) continue;
645 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);
625 const natural_align = field_ty.abiAlignment(zcu);
646626 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
647627 } else false;
648628
......@@ -654,7 +634,7 @@ fn defineUnionExtern(
654634 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
655635 const field_ty: Type = .fromInterned(field_ty_ip);
656636 if (!field_ty.hasRuntimeBits(zcu)) continue;
657 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);
637 const natural_align = field_ty.abiAlignment(zcu);
658638 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
659639 } else overalign: {
660640 if (union_type.has_runtime_tag) {
......@@ -668,9 +648,8 @@ fn defineUnionExtern(
668648 if (pack) try w.writeAll("zig_packed(");
669649
670650 const name_cty: CType = .{ .union_extern = ty };
671 try w.print("{f} {{ /* {f} */\n", .{
651 try w.print("{f} {{\n", .{
672652 name_cty.fmtTypeName(zcu),
673 ty.fmt(pt),
674653 });
675654
676655 for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| {
......@@ -691,9 +670,8 @@ fn defineUnionExtern(
691670 }
692671 try w.writeByte('}');
693672 if (pack) try w.writeByte(')');
694 try w.writeAll(";\n");
695
696 try writeStaticAssertLayout(ty, name_cty, w, zcu);
673 try w.writeByte(';');
674 return name_cty;
697675}
698676
699677/// Writes an annotation which, placed before a struct/union field declaration with field type `ty`,
......@@ -704,7 +682,7 @@ fn writeFieldAlign(
704682 w: *Writer,
705683 zcu: *const Zcu,
706684) Writer.Error!void {
707 if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) {
685 if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
708686 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
709687 } else {
710688 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});
......@@ -712,19 +690,29 @@ fn writeFieldAlign(
712690}
713691
714692/// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`.
715fn writeStaticAssertLayout(
693pub fn writeStaticAssertTypeLayout(
716694 ty: Type,
717695 cty: CType,
718696 w: *Writer,
719697 zcu: *const Zcu,
698) Writer.Error!void {
699 try writeStaticAssertCTypeLayout(cty, ty.abiSize(zcu), ty.abiAlignment(zcu), w, zcu);
700}
701
702/// Emits static assertions that the size and alignment of `cty` match the provided values.
703pub fn writeStaticAssertCTypeLayout(
704 cty: CType,
705 expected_size: u64,
706 expected_alignment: Alignment,
707 w: *Writer,
708 zcu: *const Zcu,
720709) Writer.Error!void {
721710 try w.print(
722 \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size");
723 \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment");
711 \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch");
724712 \\
725713 , .{
726 cty.fmtTypeName(zcu), ty.abiSize(zcu),
727 cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?,
714 cty.fmtTypeName(zcu), expected_size,
715 cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?,
728716 });
729717}
730718
src/codegen/llvm.zig+693-539
......@@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool {
345345 };
346346}
347347
348pub fn dataLayout(target: *const std.Target) []const u8 {
349 // These data layouts should match Clang.
350 return switch (target.cpu.arch) {
351 .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32",
352 .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32",
353 .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048",
354 .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64",
355 .aarch64 => if (target.ofmt == .macho)
356 if (target.os.tag == .windows or target.os.tag == .uefi)
357 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
358 else if (target.abi == .ilp32)
359 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
360 else
361 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
362 else if (target.os.tag == .windows or target.os.tag == .uefi)
363 "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32"
364 else
365 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
366 .aarch64_be => "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
367 .arm => if (target.ofmt == .macho)
368 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
369 else
370 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
371 .armeb, .thumbeb => if (target.ofmt == .macho)
372 "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
373 else
374 "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
375 .thumb => if (target.ofmt == .macho)
376 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
377 else if (target.os.tag == .windows or target.os.tag == .uefi)
378 "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
379 else
380 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
381 .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8",
382 .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
383 .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
384 .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
385 .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
386 .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
387 .mips64 => switch (target.abi) {
388 .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
389 else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
390 },
391 .mips64el => switch (target.abi) {
392 .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
393 else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
394 },
395 .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
396 .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32",
397 .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
398 .powerpc64 => switch (target.os.tag) {
399 .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512",
400 .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64",
401 else => "E-m:e-Fn32-i64:64-i128:128-n32:64",
402 },
403 .powerpc64le => if (target.os.tag == .linux)
404 "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
405 else
406 "e-m:e-Fn32-i64:64-i128:128-n32:64",
407 .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
408 .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
409 .amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9",
410 .riscv32 => if (target.cpu.has(.riscv, .e))
411 "e-m:e-p:32:32-i64:64-n32-S32"
412 else
413 "e-m:e-p:32:32-i64:64-n32-S128",
414 .riscv32be => if (target.cpu.has(.riscv, .e))
415 "E-m:e-p:32:32-i64:64-n32-S32"
416 else
417 "E-m:e-p:32:32-i64:64-n32-S128",
418 .riscv64 => if (target.cpu.has(.riscv, .e))
419 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
420 else
421 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
422 .riscv64be => if (target.cpu.has(.riscv, .e))
423 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
424 else
425 "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
426 .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64",
427 .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128",
428 .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
429 .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) {
430 .gnu => if (target.ofmt == .coff)
431 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
432 else
433 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
434 else => blk: {
435 const msvc = switch (target.abi) {
436 .none, .msvc => true,
437 else => false,
438 };
439
440 break :blk if (target.ofmt == .coff)
441 if (msvc)
442 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
443 else
444 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
445 else if (msvc)
446 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
447 else
448 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32";
449 },
450 } else if (target.ofmt == .macho)
451 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128"
452 else
453 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
454 .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
455 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
456 else switch (target.abi) {
457 .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
458 else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff)
459 "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
460 else
461 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
462 },
463 .spirv32 => switch (target.os.tag) {
464 .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
465 else => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
466 },
467 .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
468 .wasm32 => if (target.os.tag == .emscripten)
469 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20"
470 else
471 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
472 .wasm64 => if (target.os.tag == .emscripten)
473 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20"
474 else
475 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20",
476 .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64",
477 .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32",
478 .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128",
479 .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
480 .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32",
481
482 .alpha,
483 .arceb,
484 .ez80,
485 .hppa,
486 .hppa64,
487 .kalimba,
488 .kvx,
489 .m88k,
490 .microblaze,
491 .microblazeel,
492 .or1k,
493 .propeller,
494 .sh,
495 .sheb,
496 .x86_16,
497 .xtensaeb,
498 => unreachable, // Gated by hasLlvmSupport().
499 };
500}
501
502348// Avoid depending on `bindings.CodeModel` in the bitcode-only case.
503349const CodeModel = enum {
504350 default,
......@@ -573,6 +419,8 @@ pub const Object = struct {
573419 val: InternPool.Index,
574420 @"addrspace": std.lang.AddressSpace,
575421 }, Builder.Variable.Index),
422 /// Same as `uav_map` but for llvm values not originating from the frontend.
423 const_map: std.AutoHashMapUnmanaged(Builder.Constant, Builder.Variable.Index),
576424 /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction.
577425 enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index),
578426 /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction.
......@@ -616,8 +464,6 @@ pub const Object = struct {
616464 });
617465 errdefer builder.deinit();
618466
619 builder.data_layout = try builder.string(dataLayout(target));
620
621467 const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
622468 if (!builder.strip) debug_info: {
623469 // We fully resolve all paths at this point to avoid lack of
......@@ -693,6 +539,7 @@ pub const Object = struct {
693539 .zcu = zcu,
694540 .nav_map = .empty,
695541 .uav_map = .empty,
542 .const_map = .empty,
696543 .enum_tag_name_map = .empty,
697544 .named_enum_map = .empty,
698545 .type_map = .empty,
......@@ -703,21 +550,22 @@ pub const Object = struct {
703550 return obj;
704551 }
705552
706 pub fn deinit(self: *Object) void {
707 const gpa = self.gpa;
708 self.type_pool.deinit(gpa);
709 self.lazy_abi_aligns.deinit(gpa);
710 self.debug_enums.deinit(gpa);
711 self.debug_globals.deinit(gpa);
712 self.debug_file_map.deinit(gpa);
713 self.debug_types.deinit(gpa);
714 self.nav_map.deinit(gpa);
715 self.uav_map.deinit(gpa);
716 self.enum_tag_name_map.deinit(gpa);
717 self.named_enum_map.deinit(gpa);
718 self.type_map.deinit(gpa);
719 self.builder.deinit();
720 self.* = undefined;
553 pub fn deinit(o: *Object) void {
554 const gpa = o.gpa;
555 o.type_pool.deinit(gpa);
556 o.lazy_abi_aligns.deinit(gpa);
557 o.debug_enums.deinit(gpa);
558 o.debug_globals.deinit(gpa);
559 o.debug_file_map.deinit(gpa);
560 o.debug_types.deinit(gpa);
561 o.nav_map.deinit(gpa);
562 o.uav_map.deinit(gpa);
563 o.const_map.deinit(gpa);
564 o.enum_tag_name_map.deinit(gpa);
565 o.named_enum_map.deinit(gpa);
566 o.type_map.deinit(gpa);
567 o.builder.deinit();
568 o.* = undefined;
721569 }
722570
723571 fn genErrorNameTable(o: *Object) Allocator.Error!void {
......@@ -741,16 +589,16 @@ pub const Object = struct {
741589 for (llvm_errors[1..], error_name_list) |*llvm_error, name| {
742590 const name_string = try o.builder.stringNull(name.toSlice(ip));
743591 const name_init = try o.builder.stringConst(name_string);
744 const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
745 try name_variable_index.setInitializer(name_init, &o.builder);
746 name_variable_index.setMutability(.constant, &o.builder);
747 name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder);
748 const global_index = name_variable_index.ptrConst(&o.builder).global;
749 global_index.setLinkage(.private, &o.builder);
750 global_index.setUnnamedAddr(.unnamed_addr, &o.builder);
592 const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
593 try name_llvm_variable.setInitializer(name_init, &o.builder);
594 name_llvm_variable.setMutability(.constant, &o.builder);
595 name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
596 const llvm_global = name_llvm_variable.ptrConst(&o.builder).global;
597 llvm_global.setLinkage(.private, &o.builder);
598 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
751599
752600 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
753 name_variable_index.toConst(&o.builder),
601 name_llvm_variable.toConst(&o.builder),
754602 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1),
755603 });
756604 }
......@@ -1199,19 +1047,33 @@ pub const Object = struct {
11991047 global.dll_storage_class = .default;
12001048 global.unnamed_addr = .unnamed_addr;
12011049 }
1202 llvm_function.setAlignment(switch (nav.resolved.?.@"align") {
1203 .none => fn_ty.abiAlignment(zcu).toLlvm(),
1204 else => |a| a.toLlvm(),
1205 }, &o.builder);
1050 llvm_function.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder);
12061051 llvm_function.setSection(s: {
12071052 const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none;
12081053 break :s try o.builder.string(section);
12091054 }, &o.builder);
1210 try o.addLlvmFunctionAttributes(pt, func.owner_nav, llvm_function);
12111055
1212 var attributes = try llvm_function.ptrConst(&o.builder).attributes.toWip(&o.builder);
1056 var attributes: Builder.FunctionAttributes.Wip = .{};
12131057 defer attributes.deinit(&o.builder);
12141058
1059 // Function attributes that are independent of analysis results of the function body.
1060 try o.addCommonFnAttributes(
1061 &attributes,
1062 owner_mod,
1063 // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`,
1064 // so for these backends, LLVM will happily emit code that accesses the stack through
1065 // the frame pointer. This is nonsensical since what the `naked` attribute does is
1066 // suppress generation of the prologue and epilogue, and the prologue is where the
1067 // frame pointer normally gets set up. At time of writing, this is the case for at
1068 // least x86 and RISC-V.
1069 owner_mod.omit_frame_pointer or fn_info.cc == .naked,
1070 );
1071
1072 try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, if (nav.getExtern(ip)) |@"extern"| .{
1073 .name = nav.name.toSlice(ip),
1074 .lib_name = @"extern".lib_name.toSlice(ip),
1075 } else null, .fromIntern(fn_info, ip));
1076
12151077 const func_analysis = func.analysisUnordered(ip);
12161078 if (func_analysis.is_noinline) {
12171079 try attributes.addFnAttr(.@"noinline", &o.builder);
......@@ -1324,7 +1186,7 @@ pub const Object = struct {
13241186 const counters_variable = try o.builder.addVariable(anon_name, .void, .default);
13251187 try o.used.append(gpa, counters_variable.toConst(&o.builder));
13261188 counters_variable.ptrConst(&o.builder).global.setLinkage(.private, &o.builder);
1327 counters_variable.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
1189 counters_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
13281190
13291191 if (target.ofmt == .macho) {
13301192 counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder);
......@@ -1507,10 +1369,6 @@ pub const Object = struct {
15071369 llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr;
15081370 }
15091371
1510 const llvm_align = switch (resolved.@"align") {
1511 .none => nav_ty.abiAlignment(zcu).toLlvm(),
1512 else => |a| a.toLlvm(),
1513 };
15141372 const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: {
15151373 break :s try o.builder.string(section);
15161374 } else .none;
......@@ -1519,13 +1377,20 @@ pub const Object = struct {
15191377 // can see are extern functions or other comptime function body values (e.g. undefined). Of
15201378 // these, only extern functions need to be lowered to LLVM functions.
15211379 if (opt_extern != null and nav_ty.zigTypeTag(zcu) == .@"fn" and nav_ty.fnHasRuntimeBits(zcu)) {
1380 const fn_info = zcu.typeToFunc(nav_ty).?;
15221381 const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) {
15231382 .function => |function| function, // re-use existing `Builder.Function`
15241383 .replaced, .alias, .variable => try llvm_global.toNewFunction(&o.builder),
15251384 };
1526 llvm_function.setAlignment(llvm_align, &o.builder);
1385 llvm_function.setAlignment(resolved.@"align".toLlvm(), &o.builder);
15271386 llvm_function.setSection(llvm_section, &o.builder);
1528 try o.addLlvmFunctionAttributes(pt, nav_id, llvm_function);
1387 var attributes: Builder.FunctionAttributes.Wip = .{};
1388 defer attributes.deinit(&o.builder);
1389 try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{
1390 .name = nav.name.toSlice(ip),
1391 .lib_name = opt_extern.?.lib_name.toSlice(ip),
1392 }, .fromIntern(fn_info, ip));
1393 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
15291394 } else {
15301395 const file_scope = nav.srcInst(ip).resolveFile(ip);
15311396 const mod = zcu.fileByIndex(file_scope).mod.?;
......@@ -1534,7 +1399,10 @@ pub const Object = struct {
15341399 .variable => |variable| variable, // re-use existing `Builder.Variable`
15351400 .replaced, .alias, .function => try llvm_global.toNewVariable(&o.builder),
15361401 };
1537 llvm_variable.setAlignment(llvm_align, &o.builder);
1402 llvm_variable.setAlignment(switch (resolved.@"align") {
1403 .none => nav_ty.abiAlignment(zcu).toLlvm(),
1404 else => |a| a.toLlvm(),
1405 }, &o.builder);
15381406 llvm_variable.setSection(llvm_section, &o.builder);
15391407 llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder);
15401408 try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value, .in_memory), &o.builder);
......@@ -1585,7 +1453,7 @@ pub const Object = struct {
15851453 const uav_ty = Value.fromInterned(uav).typeOf(zcu);
15861454 const uav_ref = try o.lowerUavRef(
15871455 uav,
1588 uav_ty.abiAlignment(zcu),
1456 uav_ty.abiAlignment(zcu).toLlvm(),
15891457 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),
15901458 );
15911459 break :exp .{ uav_ty, uav_ref };
......@@ -1599,7 +1467,7 @@ pub const Object = struct {
15991467
16001468 fn updateExportedGlobal(
16011469 o: *Object,
1602 global_index: Builder.Global.Index,
1470 llvm_global: Builder.Global.Index,
16031471 ty: Type,
16041472 export_indices: []const Zcu.Export.Index,
16051473 ) link.Error!void {
......@@ -1634,11 +1502,11 @@ pub const Object = struct {
16341502 // make much sense: the linksection should be associated with the declaration itself rather
16351503 // than some particular symbol it is exported as!
16361504 if (export_indices[0].ptr(zcu).opts.section.toSlice(ip)) |section_slice| {
1637 const variable = &global_index.ptrConst(&o.builder).kind.variable;
1505 const variable = &llvm_global.ptrConst(&o.builder).kind.variable;
16381506 variable.setSection(try o.builder.string(section_slice), &o.builder);
16391507 }
16401508
1641 const llvm_global_ty = global_index.typeOf(&o.builder);
1509 const llvm_global_ty = llvm_global.typeOf(&o.builder);
16421510
16431511 // All exports are represented as aliases to the original global.
16441512
......@@ -1661,8 +1529,8 @@ pub const Object = struct {
16611529 const alias = try o.builder.addAlias(
16621530 exp_name,
16631531 llvm_global_ty,
1664 global_index.ptrConst(&o.builder).addr_space,
1665 global_index.toConst(),
1532 llvm_global.ptrConst(&o.builder).addr_space,
1533 llvm_global.toConst(),
16661534 );
16671535 break :global alias.ptrConst(&o.builder).global;
16681536 };
......@@ -1671,12 +1539,9 @@ pub const Object = struct {
16711539 switch (existing_global.ptrConst(&o.builder).kind) {
16721540 .alias => |alias| {
16731541 // We can just repurpose the existing alias.
1674 alias.setAliasee(global_index.toConst(), &o.builder);
1675 alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&o.builder);
1676 // If the type the alias is pointing to can change, then
1677 // it makes sense that we should update the address
1678 // space too.
1679 alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = global_index.ptrConst(&o.builder).addr_space;
1542 alias.setAliasee(llvm_global.toConst(), &o.builder);
1543 alias.ptrConst(&o.builder).global.ptr(&o.builder).type = llvm_global.typeOf(&o.builder);
1544 alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = llvm_global.ptrConst(&o.builder).addr_space;
16801545 break :global existing_global;
16811546 },
16821547 .variable, .function => {
......@@ -1686,13 +1551,13 @@ pub const Object = struct {
16861551 // We need to make a new global which is an alias. Replace this existing one
16871552 // with the target global, making the name available and fixing references
16881553 // to this global to point to the target.
1689 try existing_global.replace(global_index, &o.builder);
1554 try existing_global.replace(llvm_global, &o.builder);
16901555 // The name is now free, so create an alias.
16911556 const alias = try o.builder.addAlias(
16921557 exp_name,
16931558 llvm_global_ty,
1694 global_index.ptrConst(&o.builder).addr_space,
1695 global_index.toConst(),
1559 llvm_global.ptrConst(&o.builder).addr_space,
1560 llvm_global.toConst(),
16961561 );
16971562 break :global alias.ptrConst(&o.builder).global;
16981563 },
......@@ -1725,11 +1590,11 @@ pub const Object = struct {
17251590 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {
17261591 _ = o.type_map.remove(ty);
17271592 try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);
1728 if (o.named_enum_map.get(ty)) |function_index| {
1729 try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index);
1593 if (o.named_enum_map.get(ty)) |llvm_function| {
1594 try o.updateIsNamedEnumValueFunction(.fromInterned(ty), llvm_function);
17301595 }
1731 if (o.enum_tag_name_map.get(ty)) |function_index| {
1732 try o.updateEnumTagNameFunction(.fromInterned(ty), function_index);
1596 if (o.enum_tag_name_map.get(ty)) |llvm_function| {
1597 try o.updateEnumTagNameFunction(.fromInterned(ty), llvm_function);
17331598 }
17341599 }
17351600
......@@ -2102,7 +1967,7 @@ pub const Object = struct {
21021967 payload_offset * 8,
21031968 );
21041969
2105 return try o.builder.debugStructType(
1970 return o.builder.debugStructType(
21061971 name,
21071972 null, // File
21081973 o.debug_compile_unit.unwrap().?, // Scope
......@@ -2140,7 +2005,7 @@ pub const Object = struct {
21402005 defer debug_param_types.deinit(gpa);
21412006
21422007 // Return type goes first.
2143 if (try fnReturnStrat(o, fn_info) == .sret) {
2008 if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) {
21442009 // Actual return type is void, then first arg is the sret pointer.
21452010 const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type));
21462011 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void));
......@@ -2575,53 +2440,117 @@ pub const Object = struct {
25752440 fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
25762441 const zcu = o.zcu;
25772442 const namespace = zcu.namespacePtr(namespace_index);
2578 if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope);
2443 if (namespace.parent == .none) return o.getDebugFile(namespace.file_scope);
25792444 return o.getDebugType(pt, .fromInterned(namespace.owner_type));
25802445 }
25812446
2582 /// Sets the attributes and callconv of the given `Builder.Function`, which corresponds to the
2583 /// given `Nav` (which is a function).
2584 fn addLlvmFunctionAttributes(
2447 fn addCommonFnAttributes(
2448 o: *Object,
2449 attributes: *Builder.FunctionAttributes.Wip,
2450 owner_mod: *Module,
2451 omit_frame_pointer: bool,
2452 ) Allocator.Error!void {
2453 if (!owner_mod.red_zone) {
2454 try attributes.addFnAttr(.noredzone, &o.builder);
2455 }
2456 if (omit_frame_pointer) {
2457 try attributes.addFnAttr(.{ .string = .{
2458 .kind = try o.builder.string("frame-pointer"),
2459 .value = try o.builder.string("none"),
2460 } }, &o.builder);
2461 } else {
2462 try attributes.addFnAttr(.{ .string = .{
2463 .kind = try o.builder.string("frame-pointer"),
2464 .value = try o.builder.string("all"),
2465 } }, &o.builder);
2466 }
2467 try attributes.addFnAttr(.nounwind, &o.builder);
2468 if (owner_mod.unwind_tables != .none) {
2469 try attributes.addFnAttr(
2470 .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync },
2471 &o.builder,
2472 );
2473 }
2474 if (owner_mod.optimize_mode == .small) {
2475 try attributes.addFnAttr(.minsize, &o.builder);
2476 try attributes.addFnAttr(.optsize, &o.builder);
2477 }
2478 const target = &owner_mod.resolved_target.result;
2479 if (target.cpu.model.llvm_name) |s| {
2480 try attributes.addFnAttr(.{ .string = .{
2481 .kind = try o.builder.string("target-cpu"),
2482 .value = try o.builder.string(s),
2483 } }, &o.builder);
2484 }
2485 if (owner_mod.resolved_target.llvm_cpu_features) |s| {
2486 try attributes.addFnAttr(.{ .string = .{
2487 .kind = try o.builder.string("target-features"),
2488 .value = try o.builder.string(std.mem.span(s)),
2489 } }, &o.builder);
2490 }
2491 if (target.abi.float() == .soft) {
2492 // `use-soft-float` means "use software routines for floating point computations". In
2493 // other words, it configures how LLVM lowers basic float instructions like `fcmp`,
2494 // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is
2495 // mostly an orthogonal concept, although obviously we do need hardware float operations
2496 // to actually be able to pass float values in float registers.
2497 //
2498 // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC
2499 // and Clang support for Arm32 and CSKY. We don't currently expose such an option in
2500 // Zig, and using CPU features as the source of truth for this makes for a miserable
2501 // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float
2502 // unless the compiler has explicitly been told otherwise. (And note that our baseline
2503 // CPU models almost all include FPU features!)
2504 //
2505 // Revisit this at some point.
2506 try attributes.addFnAttr(.{ .string = .{
2507 .kind = try o.builder.string("use-soft-float"),
2508 .value = try o.builder.string("true"),
2509 } }, &o.builder);
2510
2511 // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the
2512 // above, this should be revisited if `softfp` support is added.
2513 try attributes.addFnAttr(.noimplicitfloat, &o.builder);
2514 }
2515 }
2516
2517 pub fn addCallingConventionFnAttributes(
25852518 o: *Object,
25862519 pt: Zcu.PerThread,
2587 nav_id: InternPool.Nav.Index,
2588 function_index: Builder.Function.Index,
2520 llvm_function: Builder.Function.Index,
2521 attributes: *Builder.FunctionAttributes.Wip,
2522 opt_extern: ?struct {
2523 name: []const u8,
2524 lib_name: ?[]const u8 = null,
2525 },
2526 fn_info: FuncInfo,
25892527 ) Allocator.Error!void {
25902528 const zcu = o.zcu;
2591 const ip = &zcu.intern_pool;
2592 const nav = ip.getNav(nav_id);
2593 const owner_mod = zcu.navFileScope(nav_id).mod.?;
2594 const ty: Type = .fromInterned(nav.resolved.?.type);
2595
2596 const fn_info = zcu.typeToFunc(ty).?;
2597 const target = &owner_mod.resolved_target.result;
2529 const target = zcu.getTarget();
25982530
2599 var attributes: Builder.FunctionAttributes.Wip = .{};
2600 defer attributes.deinit(&o.builder);
2531 if (fn_info.cc == .async) {
2532 @panic("TODO: LLVM backend lower async function");
2533 }
26012534
2602 if (target.cpu.arch.isWasm()) if (nav.getExtern(ip)) |@"extern"| {
2535 if (target.cpu.arch.isWasm()) if (opt_extern) |@"extern"| {
26032536 try attributes.addFnAttr(.{ .string = .{
26042537 .kind = try o.builder.string("wasm-import-name"),
2605 .value = try o.builder.string(nav.name.toSlice(ip)),
2538 .value = try o.builder.string(@"extern".name),
26062539 } }, &o.builder);
2607 if (@"extern".lib_name.toSlice(ip)) |lib_name_slice| {
2608 if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{
2540 if (@"extern".lib_name) |lib_name| {
2541 if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
26092542 .kind = try o.builder.string("wasm-import-module"),
2610 .value = try o.builder.string(lib_name_slice),
2543 .value = try o.builder.string(lib_name),
26112544 } }, &o.builder);
26122545 }
26132546 };
26142547
2615 if (fn_info.cc == .async) {
2616 @panic("TODO: LLVM backend lower async function");
2617 }
2618
26192548 const cc_info = toLlvmCallConv(fn_info.cc, target).?;
26202549
2621 function_index.setCallConv(cc_info.llvm_cc, &o.builder);
2550 llvm_function.setCallConv(cc_info.llvm_cc, &o.builder);
26222551
26232552 if (cc_info.align_stack) {
2624 try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder);
2553 try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("stackrealign"), .value = .empty } }, &o.builder);
26252554 }
26262555
26272556 if (cc_info.naked) {
......@@ -2672,29 +2601,16 @@ pub const Object = struct {
26722601 else => {},
26732602 }
26742603
2675 // Function attributes that are independent of analysis results of the function body.
2676 try o.addCommonFnAttributes(
2677 &attributes,
2678 owner_mod,
2679 // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`,
2680 // so for these backends, LLVM will happily emit code that accesses the stack through
2681 // the frame pointer. This is nonsensical since what the `naked` attribute does is
2682 // suppress generation of the prologue and epilogue, and the prologue is where the
2683 // frame pointer normally gets set up. At time of writing, this is the case for at
2684 // least x86 and RISC-V.
2685 owner_mod.omit_frame_pointer or fn_info.cc == .naked,
2686 );
2687
26882604 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
26892605
2690 var it = iterateParamTypes(o, fn_info);
2691 if (try fnReturnStrat(o, fn_info) == .sret) {
2692 // Sret pointers must not be address 0
2693 try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder);
2694 try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder);
2695
2696 const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory);
2697 try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder);
2606 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
2607 if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) {
2608 try o.addSRetFnAttributes(
2609 attributes,
2610 try o.lowerType(.fromInterned(fn_info.return_type), .in_memory),
2611 Type.fromInterned(fn_info.return_type).abiAlignment(zcu).toLlvm(),
2612 .declaration,
2613 );
26982614 it.llvm_index += 1;
26992615 } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
27002616 .signed => try attributes.addRetAttr(.signext, &o.builder),
......@@ -2713,9 +2629,9 @@ pub const Object = struct {
27132629 while (try it.next()) |lowering| switch (lowering) {
27142630 .byval => {
27152631 const param_index = it.zig_index - 1;
2716 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]);
2632 const param_ty: Type = .fromInterned(fn_info.param_types[param_index]);
27172633 if (!isByRef(param_ty, zcu)) {
2718 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
2634 try o.addByValParamAttrs(pt, attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
27192635 }
27202636
27212637 if (remaining_inreg_int > 0 and
......@@ -2734,12 +2650,12 @@ pub const Object = struct {
27342650 }
27352651 },
27362652 .byref => {
2737 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
2738 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
2653 const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]);
2654 try o.addByRefParamAttrs(attributes, it.llvm_index - 1, it.byval_attr, param_ty);
27392655 },
27402656 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
27412657 .slice => {
2742 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
2658 const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]);
27432659 const ptr_info = param_ty.ptrInfo(zcu);
27442660 const llvm_ptr_index = it.llvm_index - 2;
27452661 if (std.math.cast(u5, it.zig_index - 1)) |i| {
......@@ -2771,94 +2687,205 @@ pub const Object = struct {
27712687 .i64_array,
27722688 => continue,
27732689 };
2774
2775 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
27762690 }
27772691
2778 fn addCommonFnAttributes(
2692 pub fn addSRetFnAttributes(
27792693 o: *Object,
27802694 attributes: *Builder.FunctionAttributes.Wip,
2781 owner_mod: *Module,
2782 omit_frame_pointer: bool,
2695 ret_ty: Builder.Type,
2696 ret_align: Builder.Alignment,
2697 location: enum { declaration, callsite },
27832698 ) Allocator.Error!void {
2784 if (!owner_mod.red_zone) {
2785 try attributes.addFnAttr(.noredzone, &o.builder);
2786 }
2787 if (omit_frame_pointer) {
2788 try attributes.addFnAttr(.{ .string = .{
2789 .kind = try o.builder.string("frame-pointer"),
2790 .value = try o.builder.string("none"),
2791 } }, &o.builder);
2792 } else {
2793 try attributes.addFnAttr(.{ .string = .{
2794 .kind = try o.builder.string("frame-pointer"),
2795 .value = try o.builder.string("all"),
2796 } }, &o.builder);
2797 }
2798 try attributes.addFnAttr(.nounwind, &o.builder);
2799 if (owner_mod.unwind_tables != .none) {
2800 try attributes.addFnAttr(
2801 .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync },
2802 &o.builder,
2803 );
2804 }
2805 if (owner_mod.optimize_mode == .small) {
2806 try attributes.addFnAttr(.minsize, &o.builder);
2807 try attributes.addFnAttr(.optsize, &o.builder);
2808 }
2809 const target = &owner_mod.resolved_target.result;
2810 if (target.cpu.model.llvm_name) |s| {
2811 try attributes.addFnAttr(.{ .string = .{
2812 .kind = try o.builder.string("target-cpu"),
2813 .value = try o.builder.string(s),
2814 } }, &o.builder);
2815 }
2816 if (owner_mod.resolved_target.llvm_cpu_features) |s| {
2817 try attributes.addFnAttr(.{ .string = .{
2818 .kind = try o.builder.string("target-features"),
2819 .value = try o.builder.string(std.mem.span(s)),
2820 } }, &o.builder);
2821 }
2822 if (target.abi.float() == .soft) {
2823 // `use-soft-float` means "use software routines for floating point computations". In
2824 // other words, it configures how LLVM lowers basic float instructions like `fcmp`,
2825 // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is
2826 // mostly an orthogonal concept, although obviously we do need hardware float operations
2827 // to actually be able to pass float values in float registers.
2828 //
2829 // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC
2830 // and Clang support for Arm32 and CSKY. We don't currently expose such an option in
2831 // Zig, and using CPU features as the source of truth for this makes for a miserable
2832 // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float
2833 // unless the compiler has explicitly been told otherwise. (And note that our baseline
2834 // CPU models almost all include FPU features!)
2835 //
2836 // Revisit this at some point.
2837 try attributes.addFnAttr(.{ .string = .{
2838 .kind = try o.builder.string("use-soft-float"),
2839 .value = try o.builder.string("true"),
2840 } }, &o.builder);
2841
2842 // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the
2843 // above, this should be revisited if `softfp` support is added.
2844 try attributes.addFnAttr(.noimplicitfloat, &o.builder);
2699 try attributes.addParamAttr(0, .dead_on_unwind, &o.builder);
2700 switch (location) {
2701 .declaration => try attributes.addParamAttr(0, .@"noalias", &o.builder),
2702 .callsite => {},
28452703 }
2704 try attributes.addParamAttr(0, .writeonly, &o.builder);
2705 try attributes.addParamAttr(0, .{ .captures = .none }, &o.builder);
2706 try attributes.addParamAttr(0, .{ .sret = ret_ty }, &o.builder);
2707 try attributes.addParamAttr(0, .{ .@"align" = .wrap(ret_align) }, &o.builder);
28462708 }
28472709
28482710 pub const TypeRepr = enum {
28492711 /// The representation of the type when it is being manipulated as a value in a function.
2850 /// e.g. Zig `u5` -> LLVM `i5`
2851 by_value,
2852 /// The representation of the type when it is stored in memory.
2853 /// e.g. Zig `u5` -> LLVM `i8`
2712 /// e.g. Zig `u90` -> LLVM `i90`
2713 as_value,
2714 /// The representation of the type when it is loaded from or stored to memory.
2715 /// e.g. Zig `u90` -> LLVM `i96`
2716 memory_access,
2717 /// The representation of the type when it is in memory.
2718 /// e.g. Zig `u90` -> LLVM `[12 x i8]`
28542719 in_memory,
28552720 };
28562721
2722 pub fn intType(o: *Object, bits: u16, repr: TypeRepr) Allocator.Error!Builder.Type {
2723 switch (repr) {
2724 .as_value => return o.builder.intType(bits),
2725 .memory_access, .in_memory => {},
2726 }
2727 const target = o.zcu.getTarget();
2728 const abi_size = std.zig.target.intByteSize(target, bits);
2729 const llvm_bit_width = @as(u20, 8) * abi_size;
2730 switch (repr) {
2731 .as_value => unreachable,
2732 .memory_access => {},
2733 .in_memory => {
2734 const zig_align = std.zig.target.intAlignment(target, bits);
2735 const llvm_align = o.builder.data_layout.getIntegerSpec(llvm_bit_width).abi_align;
2736 if (zig_align < llvm_align.toByteUnits().?) return o.builder.arrayType(abi_size, .i8);
2737 },
2738 }
2739 return o.builder.intType(llvm_bit_width);
2740 }
2741
28572742 pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type {
2858 return o.builder.intType(switch (repr) {
2859 .by_value => o.zcu.errorSetBits(),
2860 .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8),
2861 });
2743 return o.intType(o.zcu.errorSetBits(), repr);
2744 }
2745
2746 pub const SoftF80Layout = struct {
2747 alignment: InternPool.Alignment,
2748 /// byte offset of u64 field
2749 mantissa_offset: u64,
2750 /// byte offset of u16 field
2751 exponent_offset: u64,
2752 llvm_fields_len: u32,
2753
2754 pub const LlvmFieldTag = enum { mantissa, exponent, padding };
2755 };
2756 pub fn softF80Layout(o: *Object, opts: struct {
2757 llvm_field_tags_buf: []SoftF80Layout.LlvmFieldTag = &.{},
2758 llvm_field_types_buf: []Builder.Type = &.{},
2759 }) Allocator.Error!SoftF80Layout {
2760 const zcu = o.zcu;
2761 const target = zcu.getTarget();
2762 assert(std.zig.target.compilerRtFloatAbi(target, 80) == .soft);
2763 // Current compiler rt soft abi, which is not yet affected by endianness for simplicity:
2764 //
2765 // typedef struct { uint64_t mantissa; uint16_t exponent; } f80;
2766 //
2767 var layout: SoftF80Layout = .{
2768 .alignment = Type.f80.abiAlignment(zcu),
2769 .mantissa_offset = undefined,
2770 .exponent_offset = undefined,
2771 .llvm_fields_len = 0,
2772 };
2773 var offset: u64 = 0;
2774 for ([2]SoftF80Layout.LlvmFieldTag{ .mantissa, .exponent }, [2]Type{ .u64, .u16 }) |field_tag, field_type| {
2775 const field_align = field_type.abiAlignment(zcu);
2776 assert(field_align.compareStrict(.lte, layout.alignment));
2777 const field_offset = field_align.forward(offset);
2778 switch (field_offset - offset) {
2779 0 => {},
2780 else => |padding| {
2781 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2782 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2783 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2784 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2785 layout.llvm_fields_len += 1;
2786 },
2787 }
2788 switch (field_tag) {
2789 .mantissa => layout.mantissa_offset = field_offset,
2790 .exponent => layout.exponent_offset = field_offset,
2791 .padding => unreachable,
2792 }
2793 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2794 opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag;
2795 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2796 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory);
2797 layout.llvm_fields_len += 1;
2798 offset = field_offset + field_type.abiSize(zcu);
2799 }
2800 const end = layout.alignment.forward(offset);
2801 assert(end == Type.f80.abiSize(zcu));
2802 switch (end - offset) {
2803 0 => {},
2804 else => |padding| {
2805 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2806 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2807 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2808 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2809 layout.llvm_fields_len += 1;
2810 },
2811 }
2812 return layout;
2813 }
2814
2815 pub const SoftF128Layout = struct {
2816 alignment: InternPool.Alignment,
2817 /// byte offset of u64 field
2818 lo_offset: u64,
2819 /// byte offset of u64 field
2820 hi_offset: u64,
2821 llvm_fields_len: u32,
2822
2823 pub const LlvmFieldTag = enum { lo, hi, padding };
2824 };
2825 pub fn softF128Layout(o: *Object, opts: struct {
2826 llvm_field_tags_buf: []SoftF128Layout.LlvmFieldTag = &.{},
2827 llvm_field_types_buf: []Builder.Type = &.{},
2828 }) Allocator.Error!SoftF128Layout {
2829 const zcu = o.zcu;
2830 const target = zcu.getTarget();
2831 assert(std.zig.target.compilerRtFloatAbi(target, 128) == .soft);
2832 // Current compiler rt soft abi:
2833 //
2834 // #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
2835 // typedef struct { uint64_t hi, lo; } f128;
2836 // #else
2837 // typedef struct { uint64_t lo, hi; } f128;
2838 // #endif
2839 //
2840 var layout: SoftF128Layout = .{
2841 .alignment = Type.f128.abiAlignment(zcu),
2842 .lo_offset = undefined,
2843 .hi_offset = undefined,
2844 .llvm_fields_len = 0,
2845 };
2846 var offset: u64 = 0;
2847 for (@as([2]SoftF128Layout.LlvmFieldTag, switch (target.cpu.arch.endian()) {
2848 .big => .{ .hi, .lo },
2849 .little => .{ .lo, .hi },
2850 }), [2]Type{ .u64, .u64 }) |field_tag, field_type| {
2851 const field_align = field_type.abiAlignment(zcu);
2852 assert(field_align.compareStrict(.lte, layout.alignment));
2853 const field_offset = field_align.forward(offset);
2854 switch (field_offset - offset) {
2855 0 => {},
2856 else => |padding| {
2857 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2858 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2859 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2860 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2861 layout.llvm_fields_len += 1;
2862 },
2863 }
2864 switch (field_tag) {
2865 .lo => layout.lo_offset = field_offset,
2866 .hi => layout.hi_offset = field_offset,
2867 .padding => unreachable,
2868 }
2869 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2870 opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag;
2871 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2872 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory);
2873 layout.llvm_fields_len += 1;
2874 offset = field_offset + field_type.abiSize(zcu);
2875 }
2876 const end = layout.alignment.forward(offset);
2877 assert(end == Type.f128.abiSize(zcu));
2878 switch (end - offset) {
2879 0 => {},
2880 else => |padding| {
2881 if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len)
2882 opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding;
2883 if (layout.llvm_fields_len < opts.llvm_field_types_buf.len)
2884 opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8);
2885 layout.llvm_fields_len += 1;
2886 },
2887 }
2888 return layout;
28622889 }
28632890
28642891 pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type {
......@@ -2866,42 +2893,31 @@ pub const Object = struct {
28662893 const target = zcu.getTarget();
28672894 const ip = &zcu.intern_pool;
28682895
2869 if (repr == .by_value) {
2870 assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory
2896 switch (repr) {
2897 .as_value => assert(!isByRef(t, zcu)), // by-ref types must only be manipulated in memory
2898 .memory_access, .in_memory => {},
28712899 }
28722900
28732901 return switch (t.toIntern()) {
28742902 .u0_type => unreachable, // no runtime bits
2875 inline .u1_type,
2876 .u8_type,
2877 .i8_type,
2878 .u16_type,
2879 .i16_type,
2880 .u29_type,
2881 .u32_type,
2882 .i32_type,
2883 .u64_type,
2884 .i64_type,
2885 .u80_type,
2886 .u128_type,
2887 .i128_type,
2888 => |tag| switch (repr) {
2889 .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]),
2890 .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
2891 },
2892 .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()),
2893 inline .c_char_type,
2894 .c_short_type,
2895 .c_ushort_type,
2896 .c_int_type,
2897 .c_uint_type,
2898 .c_long_type,
2899 .c_ulong_type,
2900 .c_longlong_type,
2901 .c_ulonglong_type,
2902 => |tag| try o.builder.intType(target.cTypeBitSize(
2903 @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]),
2904 )),
2903 .u1_type => try o.intType(1, repr),
2904 .u8_type, .i8_type => try o.intType(8, repr),
2905 .u16_type, .i16_type => try o.intType(16, repr),
2906 .u29_type => try o.intType(29, repr),
2907 .u32_type, .i32_type => try o.intType(32, repr),
2908 .u64_type, .i64_type => try o.intType(64, repr),
2909 .u80_type => try o.intType(80, repr),
2910 .u128_type, .i128_type => try o.intType(128, repr),
2911 .usize_type, .isize_type => try o.intType(target.ptrBitWidth(), repr),
2912 .c_char_type => try o.intType(target.cTypeBitSize(.char).?, repr),
2913 .c_short_type => try o.intType(target.cTypeBitSize(.short).?, repr),
2914 .c_ushort_type => try o.intType(target.cTypeBitSize(.ushort).?, repr),
2915 .c_int_type => try o.intType(target.cTypeBitSize(.int).?, repr),
2916 .c_uint_type => try o.intType(target.cTypeBitSize(.uint).?, repr),
2917 .c_long_type => try o.intType(target.cTypeBitSize(.long).?, repr),
2918 .c_ulong_type => try o.intType(target.cTypeBitSize(.ulong).?, repr),
2919 .c_longlong_type => try o.intType(target.cTypeBitSize(.longlong).?, repr),
2920 .c_ulonglong_type => try o.intType(target.cTypeBitSize(.ulonglong).?, repr),
29052921 .c_longdouble_type,
29062922 .f16_type,
29072923 .f32_type,
......@@ -2909,11 +2925,44 @@ pub const Object = struct {
29092925 .f80_type,
29102926 .f128_type,
29112927 => switch (t.floatBits(target)) {
2912 16 => if (backendSupportsF16(target)) .half else .i16,
2913 32 => .float,
2914 64 => .double,
2915 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80,
2916 128 => .fp128,
2928 16 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2929 .hard => .half,
2930 .soft => .i16,
2931 },
2932 32 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2933 .hard => .float,
2934 .soft => .i32,
2935 },
2936 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2937 .hard => .double,
2938 .soft => .i64,
2939 },
2940 80 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2941 .hard => .x86_fp80,
2942 .soft => {
2943 var llvm_field_types_buf: [5]Builder.Type = undefined;
2944 const f80_layout = try o.softF80Layout(.{
2945 .llvm_field_types_buf = &llvm_field_types_buf,
2946 });
2947 return o.builder.structType(
2948 .normal,
2949 llvm_field_types_buf[0..f80_layout.llvm_fields_len],
2950 );
2951 },
2952 },
2953 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
2954 .hard => .fp128,
2955 .soft => {
2956 var llvm_field_types_buf: [5]Builder.Type = undefined;
2957 const f128_layout = try o.softF128Layout(.{
2958 .llvm_field_types_buf = &llvm_field_types_buf,
2959 });
2960 return o.builder.structType(
2961 .normal,
2962 llvm_field_types_buf[0..f128_layout.llvm_fields_len],
2963 );
2964 },
2965 },
29172966 else => unreachable,
29182967 },
29192968 .anyopaque_type => {
......@@ -2972,10 +3021,7 @@ pub const Object = struct {
29723021 .none,
29733022 => unreachable,
29743023 else => switch (ip.indexToKey(t.toIntern())) {
2975 .int_type => |int_type| switch (repr) {
2976 .by_value => try o.builder.intType(int_type.bits),
2977 .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
2978 },
3024 .int_type => |int_type| o.intType(int_type.bits, repr),
29793025 .ptr_type => |ptr_type| type: {
29803026 const ptr_ty = try o.builder.ptrType(
29813027 toLlvmAddressSpace(ptr_type.flags.address_space, target),
......@@ -2992,11 +3038,13 @@ pub const Object = struct {
29923038 array_type.lenIncludingSentinel(),
29933039 try o.lowerType(.fromInterned(array_type.child), repr),
29943040 ),
2995 .vector_type => |vector_type| o.builder.vectorType(
2996 .normal,
2997 vector_type.len,
2998 try o.lowerType(.fromInterned(vector_type.child), .by_value),
2999 ),
3041 .vector_type => |vector_type| if (isByRef(t, zcu)) {
3042 const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), repr);
3043 return o.builder.arrayType(vector_type.len, child_llvm_ty);
3044 } else {
3045 const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value);
3046 return o.builder.vectorType(.normal, vector_type.len, child_llvm_ty);
3047 },
30003048 .opt_type => |child_ty| {
30013049 // Must stay in sync with `opt_payload` logic in `lowerPtr`.
30023050 switch (Type.fromInterned(child_ty).classify(zcu)) {
......@@ -3256,8 +3304,11 @@ pub const Object = struct {
32563304 return ty;
32573305 },
32583306 .opaque_type, .spirv_type => unreachable, // no runtime bits
3259 .enum_type => try o.lowerType(t.backingIntType(zcu), repr),
3260 .func_type => |func_type| try o.lowerFnType(t, func_type),
3307 .enum_type => try o.intType(t.backingIntType(zcu).intInfo(zcu).bits, repr),
3308 .func_type => |func_type| {
3309 assert(t.fnHasRuntimeBits(zcu));
3310 return o.lowerFnType(.fromIntern(func_type, ip));
3311 },
32613312 .error_set_type, .inferred_error_set_type => try o.errorIntType(repr),
32623313 // values, not types
32633314 .undef,
......@@ -3283,14 +3334,28 @@ pub const Object = struct {
32833334 };
32843335 }
32853336
3286 fn lowerFnType(o: *Object, fn_ty: Type, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
3337 pub const FuncInfo = struct {
3338 cc: std.lang.CallingConvention,
3339 noalias_bits: u32 = 0,
3340 param_types: []const InternPool.Index,
3341 return_type: InternPool.Index = .void_type,
3342 is_var_args: bool = false,
3343
3344 pub fn fromIntern(fn_info: InternPool.Key.FuncType, ip: *InternPool) FuncInfo {
3345 return .{
3346 .cc = fn_info.cc,
3347 .noalias_bits = fn_info.noalias_bits,
3348 .param_types = fn_info.param_types.get(ip),
3349 .return_type = fn_info.return_type,
3350 .is_var_args = fn_info.is_var_args,
3351 };
3352 }
3353 };
3354 pub fn lowerFnType(o: *Object, fn_info: FuncInfo) Allocator.Error!Builder.Type {
32873355 const zcu = o.zcu;
3288 const ip = &zcu.intern_pool;
32893356 const target = zcu.getTarget();
32903357
3291 assert(fn_ty.fnHasRuntimeBits(zcu));
3292
3293 const ret_strat = try fnReturnStrat(o, fn_info);
3358 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
32943359
32953360 var llvm_params: std.ArrayList(Builder.Type) = .empty;
32963361 defer llvm_params.deinit(o.gpa);
......@@ -3305,35 +3370,35 @@ pub const Object = struct {
33053370 try llvm_params.append(o.gpa, llvm_ptr_ty);
33063371 }
33073372
3308 var it = iterateParamTypes(o, fn_info);
3373 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
33093374 while (try it.next()) |lowering| switch (lowering) {
33103375 .no_bits => continue,
33113376 .byval => {
3312 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3313 try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .by_value));
3377 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
3378 try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .memory_access else .as_value));
33143379 },
33153380 .byref, .byref_mut => {
33163381 try llvm_params.append(o.gpa, .ptr);
33173382 },
33183383 .abi_sized_int => {
3319 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3384 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
33203385 try llvm_params.append(o.gpa, try o.builder.intType(
33213386 @intCast(param_ty.abiSize(zcu) * 8),
33223387 ));
33233388 },
33243389 .slice => {
3325 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3390 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
33263391 try llvm_params.appendSlice(o.gpa, &.{
33273392 try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)),
3328 try o.lowerType(.usize, .by_value),
3393 try o.lowerType(.usize, .as_value),
33293394 });
33303395 },
33313396 .multiple_llvm_types => {
33323397 try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]);
33333398 },
33343399 .float_array => |count| {
3335 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
3336 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory);
3400 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
3401 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .memory_access);
33373402 try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty));
33383403 },
33393404 .i32_array, .i64_array => |arr_len| {
......@@ -3347,7 +3412,7 @@ pub const Object = struct {
33473412
33483413 const llvm_ret_ty: Builder.Type = switch (ret_strat) {
33493414 .void, .sret => .void,
3350 .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .by_value),
3415 .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .as_value),
33513416 .mem_cast => |llvm_ret_ty| llvm_ret_ty,
33523417 };
33533418 const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) {
......@@ -3405,7 +3470,12 @@ pub const Object = struct {
34053470 var bigint_space: Value.BigIntSpace = undefined;
34063471 const bigint = val.toBigInt(&bigint_space, zcu);
34073472 const llvm_int_ty = try o.lowerType(ty, repr);
3408 return o.builder.bigIntConst(llvm_int_ty, bigint);
3473 if (llvm_int_ty.isInteger(&o.builder))
3474 return o.builder.bigIntConst(llvm_int_ty, bigint);
3475 const buffer = try o.gpa.alloc(u8, llvm_int_ty.aggregateLen(&o.builder));
3476 defer o.gpa.free(buffer);
3477 bigint.writeTwosComplement(buffer, target.cpu.arch.endian());
3478 return o.builder.stringConst(try o.builder.string(buffer));
34093479 },
34103480 .err => |err| {
34113481 const int = zcu.intern_pool.getErrorValueIfExists(err.name).?;
......@@ -3460,18 +3530,12 @@ pub const Object = struct {
34603530 },
34613531 .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr),
34623532 .float => switch (ty.floatBits(target)) {
3463 16 => if (backendSupportsF16(target))
3464 try o.builder.halfConst(val.toFloat(f16, zcu))
3465 else
3466 try o.builder.intConst(.i16, @as(i16, @bitCast(val.toFloat(f16, zcu)))),
3467 32 => try o.builder.floatConst(val.toFloat(f32, zcu)),
3468 64 => try o.builder.doubleConst(val.toFloat(f64, zcu)),
3469 80 => if (backendSupportsF80(target))
3470 try o.builder.x86_fp80Const(val.toFloat(f80, zcu))
3471 else
3472 try o.builder.intConst(.i80, @as(i80, @bitCast(val.toFloat(f80, zcu)))),
3473 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)),
34743533 else => unreachable,
3534 16 => try o.f16Const(val.toFloat(f16, zcu)),
3535 32 => try o.f32Const(val.toFloat(f32, zcu)),
3536 64 => try o.f64Const(val.toFloat(f64, zcu)),
3537 80 => try o.f80Const(val.toFloat(f80, zcu)),
3538 128 => try o.f128Const(val.toFloat(f128, zcu)),
34753539 },
34763540 .ptr => try o.lowerPtr(arg_val, 0),
34773541 .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{
......@@ -3590,12 +3654,13 @@ pub const Object = struct {
35903654 },
35913655 .vector_type => |vector_type| {
35923656 const vector_ty = try o.lowerType(ty, repr);
3657 const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
3658 var bfa_buf: ExpectedContents = undefined;
3659 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa);
3660 const allocator = bfa.allocator();
3661 const is_by_ref = isByRef(ty, zcu);
35933662 switch (aggregate.storage) {
35943663 .bytes, .elems => {
3595 const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
3596 var bfa_buf: ExpectedContents = undefined;
3597 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa);
3598 const allocator = bfa.allocator();
35993664 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
36003665 defer allocator.free(vals);
36013666
......@@ -3604,16 +3669,21 @@ pub const Object = struct {
36043669 result_val.* = try o.builder.intConst(.i8, byte);
36053670 },
36063671 .elems => |elems| for (vals, elems) |*result_val, elem| {
3607 result_val.* = try o.lowerValue(elem, .by_value);
3672 result_val.* = try o.lowerValue(elem, if (is_by_ref) repr else .as_value);
36083673 },
36093674 .repeated_elem => unreachable,
36103675 }
3611 return o.builder.vectorConst(vector_ty, vals);
3676 return if (is_by_ref)
3677 o.builder.arrayConst(vector_ty, vals)
3678 else
3679 o.builder.vectorConst(vector_ty, vals);
36123680 },
3613 .repeated_elem => |elem| return o.builder.splatConst(
3614 vector_ty,
3615 try o.lowerValue(elem, .by_value),
3616 ),
3681 .repeated_elem => |elem| if (is_by_ref) {
3682 const vals = try allocator.alloc(Builder.Constant, vector_type.len);
3683 defer allocator.free(vals);
3684 @memset(vals, try o.lowerValue(elem, repr));
3685 return o.builder.arrayConst(vector_ty, vals);
3686 } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)),
36173687 }
36183688 },
36193689 .tuple_type => |tuple| {
......@@ -3841,6 +3911,117 @@ pub const Object = struct {
38413911 };
38423912 }
38433913
3914 pub fn f16Const(o: *Object, val: f16) Allocator.Error!Builder.Constant {
3915 return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 16)) {
3916 .hard => o.builder.halfConst(val),
3917 .soft => o.builder.intConst(.i16, @as(u16, @bitCast(val))),
3918 };
3919 }
3920
3921 pub fn f32Const(o: *Object, val: f32) Allocator.Error!Builder.Constant {
3922 return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 32)) {
3923 .hard => o.builder.floatConst(val),
3924 .soft => o.builder.intConst(.i32, @as(u32, @bitCast(val))),
3925 };
3926 }
3927
3928 pub fn f64Const(o: *Object, val: f64) Allocator.Error!Builder.Constant {
3929 return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 64)) {
3930 .hard => o.builder.doubleConst(val),
3931 .soft => o.builder.intConst(.i64, @as(u64, @bitCast(val))),
3932 };
3933 }
3934
3935 pub fn f80Const(o: *Object, val: f80) Allocator.Error!Builder.Constant {
3936 switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 80)) {
3937 .hard => return o.builder.x86_fp80Const(val),
3938 .soft => {},
3939 }
3940 var llvm_field_tags_buf: [5]SoftF80Layout.LlvmFieldTag = undefined;
3941 var llvm_field_types_buf: [5]Builder.Type = undefined;
3942 const f80_layout = try o.softF80Layout(.{
3943 .llvm_field_tags_buf = &llvm_field_tags_buf,
3944 .llvm_field_types_buf = &llvm_field_types_buf,
3945 });
3946 const llvm_field_types = llvm_field_types_buf[0..f80_layout.llvm_fields_len];
3947 const f80_llvm_ty = try o.builder.structType(.normal, llvm_field_types);
3948 const f80_repr: packed struct { mantissa: u64, exponent: u16 } = @bitCast(val);
3949 var llvm_field_vals_buf: [5]Builder.Constant = undefined;
3950 const llvm_field_vals = llvm_field_vals_buf[0..f80_layout.llvm_fields_len];
3951 for (
3952 llvm_field_vals,
3953 llvm_field_tags_buf[0..f80_layout.llvm_fields_len],
3954 llvm_field_types,
3955 ) |*llvm_field_val, llvm_field_tag, llvm_field_type|
3956 llvm_field_val.* = switch (llvm_field_tag) {
3957 .mantissa => try o.builder.intConst(llvm_field_type, f80_repr.mantissa),
3958 .exponent => try o.builder.intConst(llvm_field_type, f80_repr.exponent),
3959 .padding => try o.builder.undefConst(llvm_field_type),
3960 };
3961 return o.builder.structConst(f80_llvm_ty, llvm_field_vals);
3962 }
3963
3964 pub fn f128Const(o: *Object, val: f128) Allocator.Error!Builder.Constant {
3965 switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 128)) {
3966 .hard => return o.builder.fp128Const(val),
3967 .soft => {},
3968 }
3969 var llvm_field_tags_buf: [5]SoftF128Layout.LlvmFieldTag = undefined;
3970 var llvm_field_types_buf: [5]Builder.Type = undefined;
3971 const f128_layout = try o.softF128Layout(.{
3972 .llvm_field_tags_buf = &llvm_field_tags_buf,
3973 .llvm_field_types_buf = &llvm_field_types_buf,
3974 });
3975 const llvm_field_types = llvm_field_types_buf[0..f128_layout.llvm_fields_len];
3976 const f128_llvm_ty = try o.builder.structType(.normal, llvm_field_types);
3977 const f128_repr: packed struct { lo: u64, hi: u64 } = @bitCast(val);
3978 var llvm_field_vals_buf: [5]Builder.Constant = undefined;
3979 const llvm_field_vals = llvm_field_vals_buf[0..f128_layout.llvm_fields_len];
3980 for (
3981 llvm_field_vals,
3982 llvm_field_tags_buf[0..f128_layout.llvm_fields_len],
3983 llvm_field_types,
3984 ) |*llvm_field_val, llvm_field_tag, llvm_field_type|
3985 llvm_field_val.* = switch (llvm_field_tag) {
3986 .lo => try o.builder.intConst(llvm_field_type, f128_repr.lo),
3987 .hi => try o.builder.intConst(llvm_field_type, f128_repr.hi),
3988 .padding => try o.builder.undefConst(llvm_field_type),
3989 };
3990 return o.builder.structConst(f128_llvm_ty, llvm_field_vals);
3991 }
3992
3993 pub fn lowerConstRef(
3994 o: *Object,
3995 constant: Builder.Constant,
3996 @"align": Builder.Alignment,
3997 ) Allocator.Error!Builder.Constant {
3998 assert(@"align" != .default);
3999 const zcu = o.zcu;
4000 const gpa = zcu.comp.gpa;
4001 const gop = try o.const_map.getOrPut(gpa, constant);
4002 if (gop.found_existing) {
4003 // Keep the greater of the two alignments.
4004 const llvm_variable = gop.value_ptr.*;
4005 const llvm_old_align = llvm_variable.getAlignment(&o.builder);
4006 const llvm_new_align = llvm_old_align.max(@"align");
4007 llvm_variable.setAlignment(llvm_new_align, &o.builder);
4008 return llvm_variable.ptrConst(&o.builder).global.toConst();
4009 }
4010 errdefer assert(o.const_map.remove(constant));
4011
4012 const llvm_ty = constant.typeOf(&o.builder);
4013 const llvm_addrspace = toLlvmAddressSpace(.generic, zcu.getTarget());
4014 const llvm_variable = try o.builder.addVariable(.empty, llvm_ty, llvm_addrspace);
4015 gop.value_ptr.* = llvm_variable;
4016 try llvm_variable.setInitializer(constant, &o.builder);
4017 llvm_variable.setMutability(.constant, &o.builder);
4018 llvm_variable.setAlignment(@"align", &o.builder);
4019 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4020 llvm_global.setLinkage(.private, &o.builder);
4021 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
4022 return llvm_global.toConst();
4023 }
4024
38444025 fn lowerPtr(
38454026 o: *Object,
38464027 ptr_val: InternPool.Index,
......@@ -3860,7 +4041,7 @@ pub const Object = struct {
38604041 const orig_ptr_ty: Type = .fromInterned(uav.orig_ty);
38614042 const base_ptr = try o.lowerUavRef(
38624043 uav.val,
3863 orig_ptr_ty.ptrAlignment(zcu),
4044 orig_ptr_ty.ptrAlignment(zcu).toLlvm(),
38644045 orig_ptr_ty.ptrAddressSpace(zcu),
38654046 );
38664047 return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{
......@@ -3869,8 +4050,8 @@ pub const Object = struct {
38694050 },
38704051 .int => try o.builder.castConst(
38714052 .inttoptr,
3872 try o.builder.intConst(try o.lowerType(.usize, .by_value), offset),
3873 try o.lowerType(.fromInterned(ptr.ty), .by_value),
4053 try o.builder.intConst(try o.lowerType(.usize, .as_value), offset),
4054 try o.lowerType(.fromInterned(ptr.ty), .as_value),
38744055 ),
38754056 .eu_payload => |eu_ptr| try o.lowerPtr(
38764057 eu_ptr,
......@@ -3912,12 +4093,12 @@ pub const Object = struct {
39124093
39134094 pub fn lowerPtrToVoid(
39144095 o: *Object,
3915 /// Must not be `.none`.
3916 @"align": InternPool.Alignment,
4096 /// Must not be `.default`.
4097 @"align": Builder.Alignment,
39174098 @"addrspace": std.lang.AddressSpace,
39184099 ) Allocator.Error!Builder.Constant {
39194100 const addr: u64 = @"align".toByteUnits().?;
3920 const llvm_usize = try o.lowerType(.usize, .by_value);
4101 const llvm_usize = try o.lowerType(.usize, .as_value);
39214102 const llvm_addr = try o.builder.intConst(llvm_usize, addr);
39224103 const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget()));
39234104 return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty);
......@@ -3926,11 +4107,11 @@ pub const Object = struct {
39264107 pub fn lowerUavRef(
39274108 o: *Object,
39284109 uav_val: InternPool.Index,
3929 /// Must not be `.none`.
3930 @"align": InternPool.Alignment,
4110 /// Must not be `.default`.
4111 @"align": Builder.Alignment,
39314112 @"addrspace": std.lang.AddressSpace,
39324113 ) Allocator.Error!Builder.Constant {
3933 assert(@"align" != .none);
4114 assert(@"align" != .default);
39344115
39354116 const zcu = o.zcu;
39364117 const ip = &zcu.intern_pool;
......@@ -3955,19 +4136,18 @@ pub const Object = struct {
39554136 // Keep the greater of the two alignments.
39564137 const llvm_variable = gop.value_ptr.*;
39574138 const llvm_old_align = llvm_variable.getAlignment(&o.builder);
3958 const llvm_new_align = llvm_old_align.max(@"align".toLlvm());
4139 const llvm_new_align = llvm_old_align.max(@"align");
39594140 llvm_variable.setAlignment(llvm_new_align, &o.builder);
39604141 return llvm_variable.ptrConst(&o.builder).global.toConst();
39614142 }
39624143 errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" }));
39634144
3964 const llvm_ty = try o.lowerType(uav_ty, .in_memory);
39654145 const llvm_name = try o.builder.strtabStringFmt("__anon_{d}", .{@backingInt(uav_val)});
3966 const llvm_variable = try o.builder.addVariable(llvm_name, llvm_ty, llvm_addrspace);
4146 const llvm_variable = try o.builder.addVariable(llvm_name, .void, llvm_addrspace);
39674147 gop.value_ptr.* = llvm_variable;
39684148 try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder);
39694149 llvm_variable.setMutability(.constant, &o.builder);
3970 llvm_variable.setAlignment(@"align".toLlvm(), &o.builder);
4150 llvm_variable.setAlignment(@"align", &o.builder);
39714151 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
39724152 llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
39734153 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
......@@ -3986,7 +4166,7 @@ pub const Object = struct {
39864166 .none => nav_ty.abiAlignment(zcu),
39874167 else => |a| a,
39884168 };
3989 return o.lowerPtrToVoid(nav_align, nav.resolved.?.@"addrspace");
4169 return o.lowerPtrToVoid(nav_align.toLlvm(), nav.resolved.?.@"addrspace");
39904170 }
39914171
39924172 const gop = try o.nav_map.getOrPut(gpa, nav_id);
......@@ -4015,7 +4195,7 @@ pub const Object = struct {
40154195 attributes: *Builder.FunctionAttributes.Wip,
40164196 param_ty: Type,
40174197 param_index: u32,
4018 fn_info: InternPool.Key.FuncType,
4198 fn_info: FuncInfo,
40194199 llvm_arg_i: u32,
40204200 ) Allocator.Error!void {
40214201 const zcu = o.zcu;
......@@ -4055,19 +4235,26 @@ pub const Object = struct {
40554235 };
40564236 }
40574237
4238 pub const Byval = struct { alignment: InternPool.Alignment = .none };
40584239 pub fn addByRefParamAttrs(
40594240 o: *Object,
40604241 attributes: *Builder.FunctionAttributes.Wip,
40614242 llvm_arg_i: u32,
4062 byval: bool,
4243 maybe_byval: ?Byval,
40634244 param_ty: Type,
40644245 ) Allocator.Error!void {
40654246 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
4066 const alignment = param_ty.abiAlignment(o.zcu).toLlvm();
4067 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
40684247 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4069 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder);
4070 if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);
4248 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4249 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
4250 const alignment = if (maybe_byval) |byval| alignment: {
4251 try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);
4252 break :alignment byval.alignment;
4253 } else .none;
4254 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(switch (alignment) {
4255 .none => param_ty.abiAlignment(o.zcu),
4256 else => alignment,
4257 }.toLlvm()) }, &o.builder);
40714258 }
40724259
40734260 pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {
......@@ -4075,18 +4262,18 @@ pub const Object = struct {
40754262
40764263 const name = try o.builder.strtabString("__zig_error_name_table");
40774264 // TODO: Address space
4078 const variable_index = try o.builder.addVariable(name, .ptr, .default);
4079 variable_index.setMutability(.constant, &o.builder);
4080 variable_index.setAlignment(
4265 const llvm_variable = try o.builder.addVariable(name, .ptr, .default);
4266 llvm_variable.setMutability(.constant, &o.builder);
4267 llvm_variable.setAlignment(
40814268 Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(),
40824269 &o.builder,
40834270 );
4084 const global_index = variable_index.ptrConst(&o.builder).global;
4085 global_index.setLinkage(.private, &o.builder);
4086 global_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4271 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4272 llvm_global.setLinkage(.private, &o.builder);
4273 llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
40874274
4088 o.error_name_table = variable_index;
4089 return variable_index;
4275 o.error_name_table = llvm_variable;
4276 return llvm_variable;
40904277 }
40914278
40924279 pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index {
......@@ -4094,13 +4281,13 @@ pub const Object = struct {
40944281 if (o.errors_len_variable == .none) {
40954282 const llvm_err_int_ty = try o.errorIntType(.in_memory);
40964283 const name = try builder.strtabString("__zig_errors_len");
4097 const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default);
4098 variable_index.setMutability(.constant, builder);
4099 variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder);
4100 const global_index = variable_index.ptrConst(&o.builder).global;
4101 global_index.setLinkage(.private, builder);
4102 global_index.setUnnamedAddr(.unnamed_addr, builder);
4103 o.errors_len_variable = variable_index;
4284 const llvm_variable = try builder.addVariable(name, llvm_err_int_ty, .default);
4285 llvm_variable.setMutability(.constant, builder);
4286 llvm_variable.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder);
4287 const llvm_global = llvm_variable.ptrConst(&o.builder).global;
4288 llvm_global.setLinkage(.private, builder);
4289 llvm_global.setUnnamedAddr(.unnamed_addr, builder);
4290 o.errors_len_variable = llvm_variable;
41044291 }
41054292 return o.errors_len_variable;
41064293 }
......@@ -4112,43 +4299,43 @@ pub const Object = struct {
41124299 const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern());
41134300 if (gop.found_existing) return gop.value_ptr.*;
41144301 errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern()));
4115 const function_index = try o.builder.addFunction(
4302 const llvm_function = try o.builder.addFunction(
41164303 // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type.
41174304 // TODO: change the builder API so we don't need to do this.
41184305 try o.builder.fnType(.void, &.{}, .normal),
41194306 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
41204307 toLlvmAddressSpace(.generic, zcu.getTarget()),
41214308 );
4122 gop.value_ptr.* = function_index;
4123 try o.updateEnumTagNameFunction(enum_ty, function_index);
4124 return function_index;
4309 gop.value_ptr.* = llvm_function;
4310 try o.updateEnumTagNameFunction(enum_ty, llvm_function);
4311 return llvm_function;
41254312 }
41264313 fn updateEnumTagNameFunction(
41274314 o: *Object,
41284315 enum_ty: Type,
4129 function_index: Builder.Function.Index,
4316 llvm_function: Builder.Function.Index,
41304317 ) Allocator.Error!void {
41314318 const zcu = o.zcu;
41324319 const ip = &zcu.intern_pool;
41334320 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
41344321
4135 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
4136 const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value);
4137 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value);
4322 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
4323 const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value);
4324 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value);
41384325
4139 function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =
4326 llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type =
41404327 try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal);
41414328
41424329 var attributes: Builder.FunctionAttributes.Wip = .{};
41434330 defer attributes.deinit(&o.builder);
41444331 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
41454332
4146 function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4147 function_index.setCallConv(.fastcc, &o.builder);
4148 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4333 llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4334 llvm_function.setCallConv(.fastcc, &o.builder);
4335 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
41494336
41504337 var wip = try Builder.WipFunction.init(&o.builder, .{
4151 .function = function_index,
4338 .function = llvm_function,
41524339 .strip = true,
41534340 });
41544341 defer wip.deinit();
......@@ -4167,23 +4354,23 @@ pub const Object = struct {
41674354 for (0..loaded_enum.field_names.len) |field_index| {
41684355 const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
41694356 const name_init = try o.builder.stringConst(name);
4170 const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4171 try name_variable_index.setInitializer(name_init, &o.builder);
4172 name_variable_index.setMutability(.constant, &o.builder);
4173 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
4174 const name_global_index = name_variable_index.ptrConst(&o.builder).global;
4175 name_global_index.setLinkage(.private, &o.builder);
4176 name_global_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4357 const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4358 try name_llvm_variable.setInitializer(name_init, &o.builder);
4359 name_llvm_variable.setMutability(.constant, &o.builder);
4360 name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder);
4361 const name_llvm_global = name_llvm_variable.ptrConst(&o.builder).global;
4362 name_llvm_global.setLinkage(.private, &o.builder);
4363 name_llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder);
41774364
41784365 const name_val = try o.builder.structValue(llvm_ret_ty, &.{
4179 name_global_index.toConst(),
4366 name_llvm_global.toConst(),
41804367 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1),
41814368 });
41824369
41834370 const return_block = try wip.block(1, "Name");
41844371 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) {
41854372 .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered
4186 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value),
4373 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value),
41874374 };
41884375 try wip_switch.addCase(llvm_tag_val, return_block, &wip);
41894376
......@@ -4209,40 +4396,40 @@ pub const Object = struct {
42094396 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());
42104397 if (gop.found_existing) return gop.value_ptr.*;
42114398 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));
4212 const function_index = try o.builder.addFunction(
4399 const llvm_function = try o.builder.addFunction(
42134400 // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type.
42144401 // TODO: change the builder API so we don't need to do this.
42154402 try o.builder.fnType(.void, &.{}, .normal),
42164403 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}),
42174404 toLlvmAddressSpace(.generic, zcu.getTarget()),
42184405 );
4219 gop.value_ptr.* = function_index;
4220 try o.updateIsNamedEnumValueFunction(enum_ty, function_index);
4221 return function_index;
4406 gop.value_ptr.* = llvm_function;
4407 try o.updateIsNamedEnumValueFunction(enum_ty, llvm_function);
4408 return llvm_function;
42224409 }
42234410 fn updateIsNamedEnumValueFunction(
42244411 o: *Object,
42254412 enum_ty: Type,
4226 function_index: Builder.Function.Index,
4413 llvm_function: Builder.Function.Index,
42274414 ) Allocator.Error!void {
42284415 const zcu = o.zcu;
42294416 const ip = &zcu.intern_pool;
42304417 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
42314418
4232 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value);
4233 function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =
4419 const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value);
4420 llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type =
42344421 try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal);
42354422
42364423 var attributes: Builder.FunctionAttributes.Wip = .{};
42374424 defer attributes.deinit(&o.builder);
42384425 try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
42394426
4240 function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4241 function_index.setCallConv(.fastcc, &o.builder);
4242 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4427 llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder);
4428 llvm_function.setCallConv(.fastcc, &o.builder);
4429 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
42434430
42444431 var wip: Builder.WipFunction = try .init(&o.builder, .{
4245 .function = function_index,
4432 .function = llvm_function,
42464433 .strip = true,
42474434 });
42484435 defer wip.deinit();
......@@ -4256,7 +4443,7 @@ pub const Object = struct {
42564443
42574444 if (loaded_enum.field_values.len > 0) {
42584445 for (loaded_enum.field_values.get(ip)) |tag_val_ip| {
4259 const llvm_tag_val = try o.lowerValue(tag_val_ip, .by_value);
4446 const llvm_tag_val = try o.lowerValue(tag_val_ip, .as_value);
42604447 try wip_switch.addCase(llvm_tag_val, named_block, &wip);
42614448 }
42624449 } else {
......@@ -4278,20 +4465,27 @@ pub const Object = struct {
42784465
42794466 pub fn getLibcFunction(
42804467 o: *Object,
4468 pt: Zcu.PerThread,
42814469 fn_name: Builder.StrtabString,
4282 param_types: []const Builder.Type,
4283 return_type: Builder.Type,
4470 fn_info: FuncInfo,
42844471 ) Allocator.Error!Builder.Function.Index {
42854472 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {
42864473 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,
42874474 .function => |function| function,
42884475 .variable, .replaced => unreachable,
42894476 };
4290 return o.builder.addFunction(
4291 try o.builder.fnType(return_type, param_types, .normal),
4477 const llvm_function = try o.builder.addFunction(
4478 try o.lowerFnType(fn_info),
42924479 fn_name,
42934480 toLlvmAddressSpace(.generic, o.zcu.getTarget()),
42944481 );
4482 var attributes: Builder.FunctionAttributes.Wip = .{};
4483 defer attributes.deinit(&o.builder);
4484 try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{
4485 .name = fn_name.slice(&o.builder).?,
4486 }, fn_info);
4487 llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder);
4488 return llvm_function;
42954489 }
42964490};
42974491
......@@ -4328,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)
43284522 std.lang.CallingConvention.SpirvFragmentOptions,
43294523 std.lang.CallingConvention.SpirvMeshOptions,
43304524 => .{ null, 0, 0 },
4331 else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)),
4525 else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"),
43324526 },
43334527 };
43344528 return .{
......@@ -4411,6 +4605,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
44114605 .x86_16_interrupt,
44124606 .x86_sysv,
44134607 .x86_win,
4608 .x86_mingw,
44144609 .x86_thiscall_mingw,
44154610 .x86_64_x32,
44164611 .aarch64_aapcs,
......@@ -4585,47 +4780,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target:
45854780 };
45864781}
45874782
4588/// This function returns true if we expect LLVM to lower f16 correctly
4589/// and false if we expect LLVM to crash if it encounters an f16 type,
4590/// or if it produces miscompilations.
4591pub fn backendSupportsF16(target: *const std.Target) bool {
4592 return switch (target.cpu.arch) {
4593 .arm,
4594 .armeb,
4595 .thumb,
4596 .thumbeb,
4597 => target.abi.float() == .soft or target.cpu.has(.arm, .fullfp16),
4598 else => true,
4599 };
4600}
4601
4602/// This function returns true if we expect LLVM to lower x86_fp80 correctly
4603/// and false if we expect LLVM to crash if it encounters an x86_fp80 type,
4604/// or if it produces miscompilations.
4605pub fn backendSupportsF80(target: *const std.Target) bool {
4606 return switch (target.cpu.arch) {
4607 .x86, .x86_64 => !target.cpu.has(.x86, .soft_float),
4608 else => false,
4609 };
4610}
4611
4612/// This function returns true if we expect LLVM to lower f128 correctly,
4613/// and false if we expect LLVM to crash if it encounters an f128 type,
4614/// or if it produces miscompilations.
4615pub fn backendSupportsF128(target: *const std.Target) bool {
4616 return switch (target.cpu.arch) {
4617 // https://github.com/llvm/llvm-project/issues/121122
4618 .amdgcn,
4619 => false,
4620 .arm,
4621 .armeb,
4622 .thumb,
4623 .thumbeb,
4624 => target.abi.float() == .soft or target.cpu.has(.arm, .fp_armv8),
4625 else => true,
4626 };
4627}
4628
46294783/// We need to insert extra padding if LLVM's isn't enough.
46304784/// However we don't want to ever call LLVMABIAlignmentOfType or
46314785/// LLVMABISizeOfType because these functions will trip assertions
src/codegen/llvm/FuncGen.zig+1509-1028
......@@ -164,12 +164,12 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant {
164164 const zcu = o.zcu;
165165 const ty = val.typeOf(zcu);
166166 if (!isByRef(ty, zcu)) {
167 return o.lowerValue(val.toIntern(), .by_value);
167 return o.lowerValue(val.toIntern(), .as_value);
168168 } else {
169169 // We need a pointer to a global constant, i.e. a UAV.
170170 return o.lowerUavRef(
171171 val.toIntern(),
172 ty.abiAlignment(zcu),
172 ty.abiAlignment(zcu).toLlvm(),
173173 target_util.defaultAddressSpace(zcu.getTarget(), .global_constant),
174174 );
175175 }
......@@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
190190 const fn_info = zcu.typeToFunc(fn_ty).?;
191191 const param_types = fn_info.param_types.get(ip);
192192
193 var it = iterateParamTypes(o, fn_info);
193 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types.get(ip));
194194
195195 // Populate `fg.ret_ptr`...
196 fg.ret_ptr = switch (try fnReturnStrat(o, fn_info)) {
196 fg.ret_ptr = switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) {
197197 .sret => rp: {
198198 defer it.llvm_index += 1;
199199 break :rp fg.wip.arg(it.llvm_index);
......@@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
218218 switch (lowering) {
219219 .no_bits => continue,
220220 .byval => {
221 assert(!it.byval_attr);
221 assert(it.byval_attr == null);
222222 const param_index = it.zig_index - 1;
223223 const param_ty: Type = .fromInterned(param_types[param_index]);
224224 const param = fg.wip.arg(it.llvm_index - 1);
......@@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
237237 .byref, .byref_mut => {
238238 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
239239 const param = fg.wip.arg(it.llvm_index - 1);
240 const alignment = if (it.byval_attr) |byval_attr| byval_attr.alignment else .none;
240241
241 if (isByRef(param_ty, zcu)) {
242 if (alignment == .none and isByRef(param_ty, zcu)) {
242243 args.appendAssumeCapacity(param);
243244 } else {
244 args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal));
245 args.appendAssumeCapacity(try fg.load(param, alignment, param_ty, .normal));
245246 }
246247 },
247248 .abi_sized_int => {
248 assert(!it.byval_attr);
249 assert(it.byval_attr == null);
249250 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
250251 const param = fg.wip.arg(it.llvm_index - 1);
251252
......@@ -260,18 +261,18 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
260261 }
261262 },
262263 .slice => {
263 assert(!it.byval_attr);
264 assert(it.byval_attr == null);
264265 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
265266 assert(!isByRef(param_ty, zcu));
266267 const slice_val = try fg.wip.buildAggregate(
267 try o.lowerType(param_ty, .by_value),
268 try o.lowerType(param_ty, .as_value),
268269 &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) },
269270 "",
270271 );
271272 args.appendAssumeCapacity(slice_val);
272273 },
273274 .multiple_llvm_types => {
274 assert(!it.byval_attr);
275 assert(it.byval_attr == null);
275276 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
276277 const param_alignment = param_ty.abiAlignment(zcu);
277278 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
......@@ -721,29 +722,19 @@ fn genBodyDebugScope(
721722 try self.genBody(body, coverage_point);
722723}
723724
724const CallAttr = enum {
725 Auto,
726 NeverTail,
727 NeverInline,
728 AlwaysTail,
729 AlwaysInline,
730};
731
732fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value {
733 const air_call = self.air.unwrapCall(inst);
734 const args = air_call.args;
735 const o = self.object;
736 const pt = self.pt;
725fn airCall(fg: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value {
726 const o = fg.object;
737727 const zcu = o.zcu;
728 const air_call = fg.air.unwrapCall(inst);
729 const args = air_call.args;
738730 const ip = &zcu.intern_pool;
739 const callee_ty = self.typeOf(air_call.callee);
731 const callee_ty = fg.typeOf(air_call.callee);
740732 const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) {
741733 .@"fn" => callee_ty,
742734 .pointer => callee_ty.childType(zcu),
743735 else => unreachable,
744736 };
745737 const fn_info = zcu.typeToFunc(zig_fn_ty).?;
746 const return_type: Type = .fromInterned(fn_info.return_type);
747738 const llvm_fn = llvm_fn: {
748739 // If the callee is a function *body*, we need to use a pointer to the global.
749740 if (air_call.callee.toInterned()) |ip_index| switch (ip.indexToKey(ip_index)) {
......@@ -752,22 +743,54 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
752743 else => {},
753744 };
754745 // Otherwise, the operand is already a function pointer (possibly runtime-known).
755 break :llvm_fn try self.resolveInst(air_call.callee);
746 break :llvm_fn try fg.resolveInst(air_call.callee);
756747 };
748
749 const arg_types = try fg.gpa.alloc(InternPool.Index, args.len);
750 defer fg.gpa.free(arg_types);
751 const arg_values = try fg.gpa.alloc(Builder.Value, args.len);
752 defer fg.gpa.free(arg_values);
753 for (arg_types, arg_values, args) |*arg_type, *arg_value, arg| {
754 const arg_ty = fg.typeOf(arg);
755 arg_type.* = arg_ty.toIntern();
756 arg_value.* = if (arg_ty.hasRuntimeBits(zcu)) try fg.resolveInst(arg) else .none;
757 }
758 return fg.buildCall(.{
759 .is_unused = fg.liveness.isUnused(inst),
760 .modifier = modifier,
761 }, try o.lowerType(zig_fn_ty, .as_value), llvm_fn, .fromIntern(fn_info, ip), arg_types, arg_values);
762}
763
764fn buildCall(
765 fg: *FuncGen,
766 opts: struct {
767 is_unused: bool = false,
768 modifier: std.lang.CallModifier = .auto,
769 },
770 llvm_fn_ty: Builder.Type,
771 llvm_fn: Builder.Value,
772 fn_info: Object.FuncInfo,
773 arg_types: []const InternPool.Index,
774 arg_values: []const Builder.Value,
775) Allocator.Error!Builder.Value {
776 const o = fg.object;
777 const pt = fg.pt;
778 const zcu = o.zcu;
779 const return_type: Type = .fromInterned(fn_info.return_type);
757780 const target = zcu.getTarget();
758 const ret_strat = try fnReturnStrat(o, fn_info);
781 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
759782
760 var llvm_args = std.array_list.Managed(Builder.Value).init(self.gpa);
761 defer llvm_args.deinit();
783 var llvm_args: std.ArrayList(Builder.Value) = .empty;
784 defer llvm_args.deinit(fg.gpa);
762785
763786 var attributes: Builder.FunctionAttributes.Wip = .{};
764787 defer attributes.deinit(&o.builder);
765788
766 if (self.disable_intrinsics) {
789 if (fg.disable_intrinsics) {
767790 try attributes.addFnAttr(.nobuiltin, &o.builder);
768791 }
769792
770 switch (modifier) {
793 switch (opts.modifier) {
771794 .auto, .always_tail => {},
772795 .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),
773796 .no_suspend, .always_inline, .compile_time => unreachable,
......@@ -775,10 +798,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
775798
776799 const sret_alloc: ?Builder.Value = switch (ret_strat) {
777800 .sret => sret_alloc: {
778 try attributes.addParamAttr(0, .{ .sret = try o.lowerType(return_type, .in_memory) }, &o.builder);
801 const alignment = return_type.abiAlignment(zcu).toLlvm();
802 try o.addSRetFnAttributes(&attributes, try o.lowerType(return_type, .in_memory), alignment, .callsite);
779803
780 const ptr = try self.buildZigAlloca(return_type, .none);
781 try llvm_args.append(ptr);
804 const ptr = try fg.buildZigAlloca(return_type, .none);
805 try llvm_args.append(fg.gpa, ptr);
782806 break :sret_alloc ptr;
783807 },
784808 else => sret_alloc: {
......@@ -792,132 +816,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
792816
793817 const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
794818 if (err_return_tracing) {
795 assert(self.err_ret_trace != .none);
796 try llvm_args.append(self.err_ret_trace);
797 }
798
799 var it = iterateParamTypes(o, fn_info);
800 while (try it.nextCall(self, args)) |lowering| switch (lowering) {
801 .no_bits => continue,
802 .byval => {
803 const arg = args[it.zig_index - 1];
804 const param_ty = self.typeOf(arg);
805 const llvm_arg = try self.resolveInst(arg);
806 if (isByRef(param_ty, zcu)) {
807 const alignment = param_ty.abiAlignment(zcu).toLlvm();
808 // We don't need to handle non-ABI-sized integer types in memory here since they are
809 // never by-ref.
810 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
811 const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, "");
812 try llvm_args.append(loaded);
813 } else {
814 try llvm_args.append(llvm_arg);
815 }
816 },
817 .byref => {
818 const arg = args[it.zig_index - 1];
819 const param_ty = self.typeOf(arg);
820 const llvm_arg = try self.resolveInst(arg);
821 if (isByRef(param_ty, zcu)) {
822 try llvm_args.append(llvm_arg);
823 } else {
824 const arg_ptr = try self.buildZigAlloca(param_ty, .none);
825 try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
826 try llvm_args.append(arg_ptr);
827 }
828 },
829 .byref_mut => {
830 const arg = args[it.zig_index - 1];
831 const param_ty = self.typeOf(arg);
832 const llvm_arg = try self.resolveInst(arg);
833
834 const arg_ptr = try self.buildZigAlloca(param_ty, .none);
835 try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
836 try llvm_args.append(arg_ptr);
837 },
838 .abi_sized_int => {
839 const arg = args[it.zig_index - 1];
840 const param_ty = self.typeOf(arg);
841 const llvm_arg = try self.resolveInst(arg);
842 const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(zcu) * 8));
843
844 if (isByRef(param_ty, zcu)) {
845 const alignment = param_ty.abiAlignment(zcu).toLlvm();
846 const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, "");
847 try llvm_args.append(loaded);
848 } else {
849 // LLVM does not allow bitcasting structs so we must allocate
850 // a local, store as one type, and then load as another type.
851 const alignment = param_ty.abiAlignment(zcu).toLlvm();
852 const ptr = try self.buildAlloca(int_llvm_ty, alignment);
853 try self.store(ptr, .none, llvm_arg, param_ty, .normal);
854 const loaded = try self.wip.load(.normal, int_llvm_ty, ptr, alignment, "");
855 try llvm_args.append(loaded);
856 }
857 },
858 .slice => {
859 const arg = args[it.zig_index - 1];
860 const llvm_arg = try self.resolveInst(arg);
861 const ptr = try self.wip.extractValue(llvm_arg, &.{0}, "");
862 const len = try self.wip.extractValue(llvm_arg, &.{1}, "");
863 try llvm_args.appendSlice(&.{ ptr, len });
864 },
865 .multiple_llvm_types => {
866 const arg = args[it.zig_index - 1];
867 const param_ty = self.typeOf(arg);
868 const llvm_arg = try self.resolveInst(arg);
869 const param_alignment = param_ty.abiAlignment(zcu);
870 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
871 const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm());
872 try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
873
874 try llvm_args.ensureUnusedCapacity(it.types_len);
875 for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| {
876 const field_ptr = try self.ptraddConst(arg_ptr, offset);
877 const loaded = try self.wip.load(.normal, field_ty, field_ptr, param_alignment.offset(offset).toLlvm(), "");
878 llvm_args.appendAssumeCapacity(loaded);
879 }
880 },
881 .float_array => |count| {
882 const arg = args[it.zig_index - 1];
883 const arg_ty = self.typeOf(arg);
884 const arg_val = try self.resolveInst(arg);
885
886 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
887 const ptr = try self.buildZigAlloca(arg_ty, .none);
888 try self.store(ptr, .none, arg_val, arg_ty, .normal);
889 break :ptr ptr;
890 } else arg_val;
891
892 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory);
893 const array_ty = try o.builder.arrayType(count, float_ty);
819 assert(fg.err_ret_trace != .none);
820 try llvm_args.append(fg.gpa, fg.err_ret_trace);
821 }
894822
895 const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
896 try llvm_args.append(loaded);
897 },
898 .i32_array, .i64_array => |arr_len| {
899 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
900 const arg = args[it.zig_index - 1];
901 const arg_ty = self.typeOf(arg);
902 const arg_val = try self.resolveInst(arg);
903
904 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
905 const ptr = try self.buildZigAlloca(arg_ty, .none);
906 try self.store(ptr, .none, arg_val, arg_ty, .normal);
907 break :ptr ptr;
908 } else arg_val;
823 var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
824 while (try it.nextCall(arg_types)) |lowering| {
825 const arg_ty: Type = .fromInterned(arg_types[it.zig_index - 1]);
826 const arg_val = arg_values[it.zig_index - 1];
827 switch (lowering) {
828 .no_bits => continue,
829 .byval => {
830 if (isByRef(arg_ty, zcu)) {
831 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
832 // We don't need to handle non-ABI-sized integer types in memory here since they are
833 // never by-ref.
834 const llvm_arg_ty = try o.lowerType(arg_ty, .memory_access);
835 const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, "");
836 try llvm_args.append(fg.gpa, loaded);
837 } else {
838 try llvm_args.append(fg.gpa, arg_val);
839 }
840 },
841 .byref => {
842 if (isByRef(arg_ty, zcu)) {
843 try llvm_args.append(fg.gpa, arg_val);
844 } else {
845 const arg_ptr = try fg.buildZigAlloca(arg_ty, .none);
846 try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal);
847 try llvm_args.append(fg.gpa, arg_ptr);
848 }
849 },
850 .byref_mut => {
851 const arg_ptr = try fg.buildZigAlloca(arg_ty, .none);
852 try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal);
853 try llvm_args.append(fg.gpa, arg_ptr);
854 },
855 .abi_sized_int => {
856 const int_llvm_ty = try o.builder.intType(@intCast(arg_ty.abiSize(zcu) * 8));
909857
910 const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size)));
911 const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
912 try llvm_args.append(loaded);
913 },
914 };
858 if (isByRef(arg_ty, zcu)) {
859 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
860 const loaded = try fg.wip.load(.normal, int_llvm_ty, arg_val, alignment, "");
861 try llvm_args.append(fg.gpa, loaded);
862 } else {
863 // LLVM does not allow bitcasting structs so we must allocate
864 // a local, store as one type, and then load as another type.
865 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
866 const ptr = try fg.buildAlloca(int_llvm_ty, alignment);
867 try fg.store(ptr, .none, arg_val, arg_ty, .normal);
868 const loaded = try fg.wip.load(.normal, int_llvm_ty, ptr, alignment, "");
869 try llvm_args.append(fg.gpa, loaded);
870 }
871 },
872 .slice => {
873 const ptr = try fg.wip.extractValue(arg_val, &.{0}, "");
874 const len = try fg.wip.extractValue(arg_val, &.{1}, "");
875 try llvm_args.appendSlice(fg.gpa, &.{ ptr, len });
876 },
877 .multiple_llvm_types => {
878 const arg_alignment = arg_ty.abiAlignment(zcu);
879 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
880 const arg_ptr = try fg.buildAlloca(llvm_ty, arg_alignment.toLlvm());
881 try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal);
882
883 try llvm_args.ensureUnusedCapacity(fg.gpa, it.types_len);
884 for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| {
885 const field_ptr = try fg.ptraddConst(arg_ptr, offset);
886 const loaded = try fg.wip.load(.normal, field_ty, field_ptr, arg_alignment.offset(offset).toLlvm(), "");
887 llvm_args.appendAssumeCapacity(loaded);
888 }
889 },
890 .float_array => |count| {
891 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
892 const ptr = try fg.buildZigAlloca(arg_ty, .none);
893 try fg.store(ptr, .none, arg_val, arg_ty, .normal);
894 break :ptr ptr;
895 } else arg_val;
896
897 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .memory_access);
898 const array_ty = try o.builder.arrayType(count, float_ty);
899
900 const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
901 try llvm_args.append(fg.gpa, loaded);
902 },
903 .i32_array, .i64_array => |arr_len| {
904 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
905
906 const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
907 const ptr = try fg.buildZigAlloca(arg_ty, .none);
908 try fg.store(ptr, .none, arg_val, arg_ty, .normal);
909 break :ptr ptr;
910 } else arg_val;
911
912 const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size)));
913 const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
914 try llvm_args.append(fg.gpa, loaded);
915 },
916 }
917 }
915918
916919 const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?;
917920
918921 {
919922 // Add argument attributes.
920 it = iterateParamTypes(o, fn_info);
923 it = iterateParamTypes(o, fn_info.cc, fn_info.param_types);
921924 it.llvm_index += @intFromBool(ret_strat == .sret);
922925 it.llvm_index += @intFromBool(err_return_tracing);
923926 var remaining_inreg_int = cc_info.inreg_int_params;
......@@ -925,7 +928,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
925928 while (try it.next()) |lowering| switch (lowering) {
926929 .byval => {
927930 const param_index = it.zig_index - 1;
928 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
931 const param_ty = Type.fromInterned(fn_info.param_types[param_index]);
929932 if (!isByRef(param_ty, zcu)) {
930933 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
931934 }
......@@ -947,7 +950,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
947950 },
948951 .byref => {
949952 const param_index = it.zig_index - 1;
950 const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]);
953 const param_ty: Type = .fromInterned(fn_info.param_types[param_index]);
951954 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
952955 },
953956 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
......@@ -961,8 +964,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
961964 => continue,
962965
963966 .slice => {
964 assert(!it.byval_attr);
965 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
967 assert(it.byval_attr == null);
968 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
966969 const ptr_info = param_ty.ptrInfo(zcu);
967970 const llvm_arg_i = it.llvm_index - 2;
968971
......@@ -989,8 +992,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
989992 };
990993 }
991994
992 const call = try self.wip.call(
993 switch (modifier) {
995 const call = try fg.wip.call(
996 switch (opts.modifier) {
994997 .auto, .never_inline => .normal,
995998 .never_tail => .notail,
996999 .always_tail => .musttail,
......@@ -998,19 +1001,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
9981001 },
9991002 cc_info.llvm_cc,
10001003 try attributes.finish(&o.builder),
1001 try o.lowerType(zig_fn_ty, .by_value),
1004 llvm_fn_ty,
10021005 llvm_fn,
10031006 llvm_args.items,
10041007 "",
10051008 );
10061009
1007 if (fn_info.return_type == .noreturn_type and modifier != .always_tail) {
1008 return .none;
1009 }
1010
1011 if (self.liveness.isUnused(inst)) {
1012 return .none;
1013 }
1010 if (opts.is_unused) return .none;
1011 if (fn_info.return_type == .noreturn_type and opts.modifier != .always_tail) return .none;
10141012
10151013 // We exit this `switch` if we have a pointer to the return value.
10161014 const ret_val_ptr: Builder.Value = switch (ret_strat) {
......@@ -1020,15 +1018,15 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
10201018 .sret => sret_alloc.?,
10211019 .mem_cast => |llvm_ret_ty| ret_val_ptr: {
10221020 const alignment = return_type.abiAlignment(zcu).toLlvm();
1023 const ptr = try self.buildAlloca(llvm_ret_ty, alignment);
1024 _ = try self.wip.store(.normal, call, ptr, alignment);
1021 const ptr = try fg.buildAlloca(llvm_ret_ty, alignment);
1022 _ = try fg.wip.store(.normal, call, ptr, alignment);
10251023 break :ret_val_ptr ptr;
10261024 },
10271025 };
10281026 if (isByRef(return_type, zcu)) {
10291027 return ret_val_ptr;
10301028 } else {
1031 return self.load(ret_val_ptr, .none, return_type, .normal);
1029 return fg.load(ret_val_ptr, .none, return_type, .normal);
10321030 }
10331031}
10341032
......@@ -1038,7 +1036,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v
10381036 const target = zcu.getTarget();
10391037 const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl()));
10401038 const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;
1041 const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .by_value);
1039 const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .as_value);
10421040
10431041 const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav);
10441042
......@@ -1067,7 +1065,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
10671065
10681066 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
10691067
1070 const ret_strat = try fnReturnStrat(o, fn_info);
1068 const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type));
10711069 const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;
10721070 const ret_ty_align = ret_ty.abiAlignment(zcu);
10731071
......@@ -1076,7 +1074,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
10761074 .none => try self.buildZigAlloca(ret_ty, .none),
10771075 else => |rp| rp,
10781076 };
1079 const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), ret_ty.abiSize(zcu));
1077 const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), ret_ty.abiSize(zcu));
10801078 _ = try self.wip.callMemSet(
10811079 rp,
10821080 ret_ty_align.toLlvm(),
......@@ -1141,7 +1139,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void {
11411139 const ret_ty = ptr_ty.childType(zcu);
11421140 const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
11431141 const ptr = try self.resolveInst(un_op);
1144 switch (try fnReturnStrat(o, fn_info)) {
1142 switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) {
11451143 .void => _ = try self.wip.retVoid(),
11461144 .sret => {
11471145 assert(self.ret_ptr != .none);
......@@ -1165,7 +1163,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
11651163 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
11661164 const list = try self.resolveInst(ty_op.operand);
11671165 const arg_ty = ty_op.ty.toType();
1168 const llvm_arg_ty = try self.object.lowerType(arg_ty, .by_value);
1166 const llvm_arg_ty = try self.object.lowerType(arg_ty, .as_value);
11691167
11701168 return self.wip.vaArg(list, llvm_arg_ty, "");
11711169}
......@@ -1378,7 +1376,7 @@ fn lowerBlock(
13781376 if (have_block_result) {
13791377 const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) {
13801378 true => .ptr,
1381 false => try o.lowerType(inst_ty, .by_value),
1379 false => try o.lowerType(inst_ty, .as_value),
13821380 };
13831381 parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);
13841382 const phi = try self.wip.phi(llvm_ty, "");
......@@ -1485,7 +1483,7 @@ fn lowerSwitchDispatch(
14851483 const table_index = try self.wip.conv(
14861484 .unsigned,
14871485 try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""),
1488 try o.lowerType(.usize, .by_value),
1486 try o.lowerType(.usize, .as_value),
14891487 "",
14901488 );
14911489 const target_ptr_ptr = try self.ptraddScaled(
......@@ -1510,7 +1508,7 @@ fn lowerSwitchDispatch(
15101508 // The switch prongs will correspond to our scalar cases. Ranges will
15111509 // be handled by conditional branches in the `else` prong.
15121510
1513 const llvm_usize = try o.lowerType(.usize, .by_value);
1511 const llvm_usize = try o.lowerType(.usize, .as_value);
15141512 const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer)
15151513 try self.wip.cast(.ptrtoint, cond, llvm_usize, "")
15161514 else
......@@ -1725,7 +1723,7 @@ fn lowerTry(
17251723 if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
17261724 );
17271725 };
1728 const zero = try o.builder.intValue(try o.errorIntType(.by_value), 0);
1726 const zero = try o.builder.intValue(try o.errorIntType(.as_value), 0);
17291727 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
17301728
17311729 const return_block = try fg.wip.block(1, "TryRet");
......@@ -1862,8 +1860,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod
18621860 const table_includes_else = item_count != table_len;
18631861
18641862 break :jmp_table .{
1865 .min = try o.lowerValue(min.toIntern(), .by_value),
1866 .max = try o.lowerValue(max.toIntern(), .by_value),
1863 .min = try o.lowerValue(min.toIntern(), .as_value),
1864 .max = try o.lowerValue(max.toIntern(), .as_value),
18671865 .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) {
18681866 .none, .cold => .none,
18691867 .unpredictable => .unpredictable,
......@@ -2021,142 +2019,102 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder
20212019 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
20222020 const operand_ty = self.typeOf(ty_op.operand);
20232021 const array_ty = operand_ty.childType(zcu);
2024 const llvm_usize = try o.lowerType(.usize, .by_value);
2022 const llvm_usize = try o.lowerType(.usize, .as_value);
20252023 const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));
2026 const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .by_value);
2024 const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .as_value);
20272025 const operand = try self.resolveInst(ty_op.operand);
20282026 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");
20292027}
20302028
2031fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2032 const o = self.object;
2029fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
2030 const o = fg.object;
20332031 const zcu = o.zcu;
2034 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
2032 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
20352033
2036 const operand = try self.resolveInst(ty_op.operand);
2037 const operand_ty = self.typeOf(ty_op.operand);
2034 const operand = try fg.resolveInst(ty_op.operand);
2035 const operand_ty = fg.typeOf(ty_op.operand);
20382036 const operand_scalar_ty = operand_ty.scalarType(zcu);
2039 const is_signed_int = operand_scalar_ty.isSignedInt(zcu);
2037 const operand_scalar_info = operand_scalar_ty.intInfo(zcu);
20402038
2041 const dest_ty = self.typeOfIndex(inst);
2039 const dest_ty = fg.typeOfIndex(inst);
20422040 const dest_scalar_ty = dest_ty.scalarType(zcu);
2043 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
20442041 const target = zcu.getTarget();
20452042
2046 if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv(
2047 if (is_signed_int) .signed else .unsigned,
2048 operand,
2049 dest_llvm_ty,
2050 "",
2051 );
2043 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target))
2044 return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), "");
20522045
2053 const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse {
2054 return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)});
2046 const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse {
2047 return fg.todo("float_from_int on {d} bit integer", .{operand_scalar_info.bits});
20552048 };
2056 const rt_int_ty = try o.builder.intType(rt_int_bits);
2057 var extended = try self.wip.conv(
2058 if (is_signed_int) .signed else .unsigned,
2049 const vector_len = if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null;
2050 const rt_llvm_int_ty = try o.lowerType(rt_int_ty, .as_value);
2051 const extended = try fg.wip.conv(
2052 .fromStdLang(operand_scalar_info.signedness),
20592053 operand,
2060 rt_int_ty,
2054 if (vector_len) |len|
2055 try o.builder.vectorType(.normal, len, rt_llvm_int_ty)
2056 else
2057 rt_llvm_int_ty,
20612058 "",
20622059 );
2063 const dest_bits = dest_scalar_ty.floatBits(target);
2064 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
2065 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);
2066 const sign_prefix = if (is_signed_int) "" else "un";
20672060 const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{
2068 sign_prefix,
2069 compiler_rt_operand_abbrev,
2070 compiler_rt_dest_abbrev,
2061 switch (operand_scalar_info.signedness) {
2062 .signed => "",
2063 .unsigned => "un",
2064 },
2065 compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits),
2066 compilerRtFloatAbbrev(target, dest_scalar_ty.floatBits(target)),
20712067 });
2072
2073 var param_type = rt_int_ty;
2074 if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) {
2075 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
2076 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
2077 param_type = try o.builder.vectorType(.normal, 2, .i64);
2078 extended = try self.wip.cast(.bitcast, extended, param_type, "");
2079 }
2080
2081 const libc_fn = try o.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty);
2082 return self.wip.call(
2083 .normal,
2084 .ccc,
2085 .none,
2086 libc_fn.typeOf(&o.builder),
2087 libc_fn.toValue(&o.builder),
2088 &.{extended},
2089 "",
2090 );
2068 return fg.buildElementwiseCall(fn_name, .{
2069 .cc = target.cCallingConvention().?,
2070 .param_types = &.{rt_int_ty.toIntern()},
2071 .return_type = dest_scalar_ty.toIntern(),
2072 }, &.{extended}, vector_len);
20912073}
20922074
20932075fn airIntFromFloat(
2094 self: *FuncGen,
2076 fg: *FuncGen,
20952077 inst: Air.Inst.Index,
20962078 fast: Builder.FastMathKind,
20972079) TodoError!Builder.Value {
20982080 _ = fast;
20992081
2100 const o = self.object;
2082 const o = fg.object;
21012083 const zcu = o.zcu;
21022084 const target = zcu.getTarget();
2103 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
2085 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
21042086
2105 const operand = try self.resolveInst(ty_op.operand);
2106 const operand_ty = self.typeOf(ty_op.operand);
2087 const operand = try fg.resolveInst(ty_op.operand);
2088 const operand_ty = fg.typeOf(ty_op.operand);
21072089 const operand_scalar_ty = operand_ty.scalarType(zcu);
21082090
2109 const dest_ty = self.typeOfIndex(inst);
2091 const dest_ty = fg.typeOfIndex(inst);
21102092 const dest_scalar_ty = dest_ty.scalarType(zcu);
2111 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
2093 const dest_llvm_ty = try o.lowerType(dest_ty, .as_value);
2094 const dest_scalar_info = dest_scalar_ty.intInfo(zcu);
21122095
2113 if (intrinsicsAllowed(operand_scalar_ty, target)) {
2096 if (intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) {
21142097 // TODO set fast math flag
2115 return self.wip.conv(
2116 if (dest_scalar_ty.isSignedInt(zcu)) .signed else .unsigned,
2117 operand,
2118 dest_llvm_ty,
2119 "",
2120 );
2098 return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, "");
21212099 }
21222100
2123 const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse {
2124 return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)});
2101 const rt_int_ty = compilerRtPromoteInt(dest_scalar_info) orelse {
2102 return fg.todo("int_from_float to {d} bit integer", .{dest_scalar_info.bits});
21252103 };
2126 const ret_ty = try o.builder.intType(rt_int_bits);
2127 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {
2128 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
2129 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
2130 break :b try o.builder.vectorType(.normal, 2, .i64);
2131 } else ret_ty;
2132
2133 const operand_bits = operand_scalar_ty.floatBits(target);
2134 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
2135
2136 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);
2137 const sign_prefix = if (dest_scalar_ty.isSignedInt(zcu)) "" else "uns";
2138
21392104 const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{
2140 sign_prefix,
2141 compiler_rt_operand_abbrev,
2142 compiler_rt_dest_abbrev,
2105 switch (dest_scalar_info.signedness) {
2106 .signed => "",
2107 .unsigned => "uns",
2108 },
2109 compilerRtFloatAbbrev(target, operand_scalar_ty.floatBits(target)),
2110 compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits),
21432111 });
2144
2145 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
2146 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty);
2147 var result = try self.wip.call(
2148 .normal,
2149 .ccc,
2150 .none,
2151 libc_fn.typeOf(&o.builder),
2152 libc_fn.toValue(&o.builder),
2153 &.{operand},
2154 "",
2155 );
2156
2157 if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, "");
2158 if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, "");
2159 return result;
2112 const result = try fg.buildElementwiseCall(fn_name, .{
2113 .cc = target.cCallingConvention().?,
2114 .param_types = &.{operand_scalar_ty.toIntern()},
2115 .return_type = rt_int_ty.toIntern(),
2116 }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null);
2117 return fg.wip.cast(.trunc, result, try o.lowerType(dest_ty, .as_value), "");
21602118}
21612119
21622120fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {
......@@ -2167,7 +2125,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B
21672125fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {
21682126 const o = fg.object;
21692127 const zcu = o.zcu;
2170 const llvm_usize = try o.lowerType(.usize, .by_value);
2128 const llvm_usize = try o.lowerType(.usize, .as_value);
21712129 switch (ty.ptrSize(zcu)) {
21722130 .slice => {
21732131 const len = try fg.wip.extractValue(ptr, &.{1}, "");
......@@ -2365,7 +2323,7 @@ fn airAggFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.
23652323 },
23662324 .float => {
23672325 // bitcast int->float
2368 return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .by_value), "");
2326 return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .as_value), "");
23692327 },
23702328 }
23712329 }
......@@ -2395,8 +2353,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
23952353 const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu);
23962354 if (field_offset == 0) return field_ptr;
23972355
2398 const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value);
2399 const llvm_usize = try o.lowerType(.usize, .by_value);
2356 const res_ty = try o.lowerType(ty_pl.ty.toType(), .as_value);
2357 const llvm_usize = try o.lowerType(.usize, .as_value);
24002358
24012359 const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, "");
24022360 const base_ptr_int = try self.wip.bin(
......@@ -2612,7 +2570,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
26122570 const output_inst = try self.resolveInst(output.operand);
26132571 const output_ty = self.typeOf(output.operand);
26142572 assert(output_ty.zigTypeTag(zcu) == .pointer);
2615 const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .by_value);
2573 const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .as_value);
26162574
26172575 switch (constraint[0]) {
26182576 '=' => {},
......@@ -2650,7 +2608,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
26502608 llvm_ret_indirect[output.index] = false;
26512609
26522610 const ret_ty = self.typeOfIndex(inst);
2653 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .by_value);
2611 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .as_value);
26542612 llvm_ret_i += 1;
26552613 }
26562614
......@@ -2689,7 +2647,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
26892647 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip);
26902648 } else {
26912649 const alignment = arg_ty.abiAlignment(zcu).toLlvm();
2692 const arg_llvm_ty = try o.lowerType(arg_ty, .by_value);
2650 const arg_llvm_ty = try o.lowerType(arg_ty, .as_value);
26932651 const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, "");
26942652 llvm_param_values[llvm_param_i] = load_inst;
26952653 llvm_param_types[llvm_param_i] = arg_llvm_ty;
......@@ -2729,7 +2687,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
27292687 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {
27302688 if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu));
27312689
2732 break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .by_value);
2690 break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .as_value);
27332691 } else .none;
27342692
27352693 llvm_param_i += 1;
......@@ -2743,7 +2701,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
27432701 if (constraint[0] != '+') continue;
27442702
27452703 const rw_ty = self.typeOf(output.operand);
2746 const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .by_value);
2704 const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .as_value);
27472705 if (llvm_ret_indirect[output.index]) {
27482706 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];
27492707 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);
......@@ -2957,7 +2915,7 @@ fn airIsNonNull(
29572915 ));
29582916 return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), "");
29592917 }
2960 return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .by_value)), "");
2918 return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .as_value)), "");
29612919 }
29622920
29632921 comptime assert(optional_layout_version == 3);
......@@ -2986,7 +2944,7 @@ fn airIsErr(
29862944 const operand_ty = self.typeOf(un_op);
29872945 const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
29882946 const payload_ty = err_union_ty.errorUnionPayload(zcu);
2989 const zero_err = try o.builder.intValue(try o.errorIntType(.by_value), 0);
2947 const zero_err = try o.builder.intValue(try o.errorIntType(.as_value), 0);
29902948
29912949 const access_kind: Builder.MemoryAccessKind =
29922950 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
......@@ -3156,7 +3114,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
31563114 const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu);
31573115
31583116 const payload_ty = err_union_ty.errorUnionPayload(zcu);
3159 const non_error_val = try o.builder.intValue(try o.errorIntType(.by_value), 0);
3117 const non_error_val = try o.builder.intValue(try o.errorIntType(.as_value), 0);
31603118
31613119 const access_kind: Builder.MemoryAccessKind =
31623120 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
......@@ -3234,7 +3192,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!
32343192 const payload_ty = self.typeOf(ty_op.operand);
32353193 assert(payload_ty.hasRuntimeBits(zcu));
32363194 assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref
3237 const ok_err_code = try o.builder.intValue(try o.errorIntType(.by_value), 0);
3195 const ok_err_code = try o.builder.intValue(try o.errorIntType(.as_value), 0);
32383196
32393197 const result_ptr = try self.buildZigAlloca(err_un_ty, .none);
32403198
......@@ -3273,7 +3231,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
32733231 const o = self.object;
32743232 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;
32753233 const index = pl_op.payload;
3276 const llvm_usize = try o.lowerType(.usize, .by_value);
3234 const llvm_usize = try o.lowerType(.usize, .as_value);
32773235 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{
32783236 try o.builder.intValue(.i32, index),
32793237 }, "");
......@@ -3283,7 +3241,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
32833241 const o = self.object;
32843242 const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op;
32853243 const index = pl_op.payload;
3286 const llvm_isize = try o.lowerType(.isize, .by_value);
3244 const llvm_isize = try o.lowerType(.isize, .as_value);
32873245 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{
32883246 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
32893247 }, "");
......@@ -3310,7 +3268,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
33103268 .normal,
33113269 .none,
33123270 if (scalar_ty.isSignedInt(zcu)) .smin else .umin,
3313 &.{try o.lowerType(inst_ty, .by_value)},
3271 &.{try o.lowerType(inst_ty, .as_value)},
33143272 &.{ lhs, rhs },
33153273 "",
33163274 );
......@@ -3330,7 +3288,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
33303288 .normal,
33313289 .none,
33323290 if (scalar_ty.isSignedInt(zcu)) .smax else .umax,
3333 &.{try o.lowerType(inst_ty, .by_value)},
3291 &.{try o.lowerType(inst_ty, .as_value)},
33343292 &.{ lhs, rhs },
33353293 "",
33363294 );
......@@ -3342,7 +3300,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
33423300 const ptr = try self.resolveInst(bin_op.lhs);
33433301 const len = try self.resolveInst(bin_op.rhs);
33443302 const inst_ty = self.typeOfIndex(inst);
3345 return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .by_value), &.{ ptr, len }, "");
3303 return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .as_value), &.{ ptr, len }, "");
33463304}
33473305
33483306fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
......@@ -3373,7 +3331,7 @@ fn airSafeArithmetic(
33733331 const scalar_ty = inst_ty.scalarType(zcu);
33743332
33753333 const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;
3376 const llvm_inst_ty = try o.lowerType(inst_ty, .by_value);
3334 const llvm_inst_ty = try o.lowerType(inst_ty, .as_value);
33773335 const results =
33783336 try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
33793337
......@@ -3423,7 +3381,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
34233381 .normal,
34243382 .none,
34253383 if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat",
3426 &.{try o.lowerType(inst_ty, .by_value)},
3384 &.{try o.lowerType(inst_ty, .as_value)},
34273385 &.{ lhs, rhs },
34283386 "",
34293387 );
......@@ -3462,7 +3420,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
34623420 .normal,
34633421 .none,
34643422 if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat",
3465 &.{try o.lowerType(inst_ty, .by_value)},
3423 &.{try o.lowerType(inst_ty, .as_value)},
34663424 &.{ lhs, rhs },
34673425 "",
34683426 );
......@@ -3501,7 +3459,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
35013459 .normal,
35023460 .none,
35033461 if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat",
3504 &.{try o.lowerType(inst_ty, .by_value)},
3462 &.{try o.lowerType(inst_ty, .as_value)},
35053463 &.{ lhs, rhs, .@"0" },
35063464 "",
35073465 );
......@@ -3545,8 +3503,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
35453503 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
35463504 }
35473505 if (scalar_ty.isSignedInt(zcu)) {
3548 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
3549 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3506 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3507 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
35503508
35513509 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
35523510 var bfa_buf: ExpectedContents = undefined;
......@@ -3594,8 +3552,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
35943552 return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result});
35953553 }
35963554 if (scalar_ty.isSignedInt(zcu)) {
3597 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
3598 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3555 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3556 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
35993557
36003558 const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
36013559 var bfa_buf: ExpectedContents = undefined;
......@@ -3634,8 +3592,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
36343592 const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction");
36353593 return self.wip.bin(.@"add nsw", div, correction, "divCeil");
36363594 } else {
3637 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
3638 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
3595 const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value);
3596 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
36393597
36403598 const zero = try o.builder.splatValue(
36413599 inst_llvm_ty,
......@@ -3692,15 +3650,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
36923650 const lhs = try self.resolveInst(bin_op.lhs);
36933651 const rhs = try self.resolveInst(bin_op.rhs);
36943652 const inst_ty = self.typeOfIndex(inst);
3695 const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
36963653 const scalar_ty = inst_ty.scalarType(zcu);
36973654
36983655 if (scalar_ty.isRuntimeFloat()) {
36993656 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
37003657 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
37013658 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
3702 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
3703 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero });
3659 const zero = if (isByRef(inst_ty, zcu)) zero: {
3660 const zero = try o.builder.zeroInitConst(try o.lowerType(inst_ty, .in_memory));
3661 break :zero try o.lowerConstRef(zero, inst_ty.abiAlignment(zcu).toLlvm());
3662 } else try o.builder.zeroInitConst(try o.lowerType(inst_ty, .as_value));
3663 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero.toValue() });
37043664 return self.wip.select(fast, ltz, c, a, "");
37053665 }
37063666 if (scalar_ty.isSignedInt(zcu)) {
......@@ -3709,6 +3669,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
37093669 var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);
37103670 const allocator = bfa.allocator();
37113671
3672 const inst_llvm_ty = try o.lowerType(inst_ty, .as_value);
37123673 const scalar_bits = scalar_ty.intInfo(zcu).bits;
37133674 var smin_big_int: std.math.big.int.Mutable = .{
37143675 .limbs = try allocator.alloc(
......@@ -3721,7 +3682,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
37213682 defer allocator.free(smin_big_int.limbs);
37223683 smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits);
37233684 const smin = try o.builder.splatValue(inst_llvm_ty, try o.builder.bigIntConst(
3724 try o.lowerType(scalar_ty, .by_value),
3685 try o.lowerType(scalar_ty, .as_value),
37253686 smin_big_int.toConst(),
37263687 ));
37273688
......@@ -3757,7 +3718,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
37573718 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
37583719 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
37593720 const ptr_or_slice = try self.resolveInst(bin_op.lhs);
3760 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
3721 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
37613722 const ptr_ty = self.typeOf(bin_op.lhs);
37623723 const elem_ty = ptr_ty.indexableElem(zcu);
37633724 const ptr = switch (ptr_ty.ptrSize(zcu)) {
......@@ -3790,7 +3751,7 @@ fn airOverflow(
37903751 assert(isByRef(inst_ty, zcu)); // auto structs are by-ref
37913752
37923753 const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;
3793 const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);
3754 const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value);
37943755 const results =
37953756 try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
37963757
......@@ -3818,34 +3779,97 @@ fn airOverflow(
38183779}
38193780
38203781fn buildElementwiseCall(
3821 self: *FuncGen,
3822 llvm_fn: Builder.Function.Index,
3823 args_vectors: []const Builder.Value,
3824 result_vector: Builder.Value,
3825 vector_len: usize,
3782 fg: *FuncGen,
3783 fn_name: Builder.StrtabString,
3784 fn_info: Object.FuncInfo,
3785 arg_values: []const Builder.Value,
3786 vector_len: ?u32,
38263787) Allocator.Error!Builder.Value {
3827 const o = self.object;
3828 assert(args_vectors.len <= 3);
3788 const o = fg.object;
3789 const zcu = o.zcu;
3790 const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info);
3791
3792 const iterations = vector_len orelse 1;
3793 const ret_ty: Type = .fromInterned(fn_info.return_type);
3794 const ret_is_by_ref = isByRef(ret_ty, zcu);
3795 if (iterations > 1 and (fn_info.return_type == .void_type or ret_is_by_ref) and
3796 for (fn_info.param_types) |param_type| {
3797 if (!isByRef(.fromInterned(param_type), zcu)) break false;
3798 } else true)
3799 {
3800 const entry_block = fg.wip.cursor.block;
3801 const loop_block = try fg.wip.block(2, "elementwise.loop");
3802 const done_block = try fg.wip.block(1, "elementwise.done");
3803
3804 const result_ptr = if (fn_info.return_type == .void_type) .none else result_ptr: {
3805 const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory);
3806 break :result_ptr try fg.buildAlloca(
3807 if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty,
3808 ret_ty.abiAlignment(zcu).toLlvm(),
3809 );
3810 };
3811 _ = try fg.wip.br(loop_block);
38293812
3830 var i: usize = 0;
3831 var result = result_vector;
3832 while (i < vector_len) : (i += 1) {
3833 const index_i32 = try o.builder.intValue(.i32, i);
3813 fg.wip.cursor = .{ .block = loop_block };
3814 const index = try fg.wip.phi(.i32, "elementwise.index");
38343815
3835 var args: [3]Builder.Value = undefined;
3836 for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| {
3837 arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, "");
3816 var arg_elems_buf: [3]Builder.Value = undefined;
3817 const arg_elems = arg_elems_buf[0..arg_values.len];
3818 for (arg_elems, fn_info.param_types, arg_values) |*arg_elem, param_type, arg_value| {
3819 const arg_elem_ptr = try fg.ptraddScaled(arg_value, index.toValue(), Type.fromInterned(param_type).abiSize(zcu));
3820 arg_elem.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal);
38383821 }
3839 const result_elem = try self.wip.call(
3840 .normal,
3841 .ccc,
3842 .none,
3843 llvm_fn.typeOf(&o.builder),
3844 llvm_fn.toValue(&o.builder),
3845 args[0..args_vectors.len],
3846 "",
3822 const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems);
3823 if (fn_info.return_type == .void_type) {
3824 assert(result_elem == .none);
3825 } else if (result_elem != .none) {
3826 const result_elem_ptr = try fg.ptraddScaled(result_ptr, index.toValue(), ret_ty.abiSize(zcu));
3827 try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal);
3828 }
3829
3830 const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "elementwise.next_index");
3831 index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip);
3832 const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "elementwise.is_done");
3833 _ = try fg.wip.brCond(is_done, done_block, loop_block, .none);
3834
3835 fg.wip.cursor = .{ .block = done_block };
3836 return result_ptr;
3837 }
3838
3839 var result = if (fn_info.return_type == .void_type) .none else if (ret_is_by_ref) result: {
3840 const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory);
3841 break :result try fg.buildAlloca(
3842 if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty,
3843 ret_ty.abiAlignment(zcu).toLlvm(),
38473844 );
3848 result = try self.wip.insertElement(result, result_elem, index_i32, "");
3845 } else if (vector_len) |len| try o.builder.poisonValue(
3846 try o.builder.vectorType(.normal, len, try o.lowerType(ret_ty, .as_value)),
3847 ) else .none;
3848 for (0..iterations) |index| {
3849 const index_value = try o.builder.intValue(.i32, index);
3850 var arg_elems_buf: [3]Builder.Value = undefined;
3851 const arg_elems = arg_elems_buf[0..arg_values.len];
3852 for (arg_elems, fn_info.param_types, arg_values) |*arg_elem_value, param_type, arg_value| {
3853 const arg_ty: Type = .fromInterned(param_type);
3854 if (isByRef(arg_ty, zcu)) {
3855 const arg_elem_ptr = try fg.ptraddConst(arg_value, index * arg_ty.abiSize(zcu));
3856 arg_elem_value.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal);
3857 } else if (vector_len) |_| {
3858 arg_elem_value.* = try fg.wip.extractElement(arg_value, index_value, "elementwise.arg_elem");
3859 } else arg_elem_value.* = arg_value;
3860 }
3861 const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems);
3862 if (fn_info.return_type == .void_type) {
3863 assert(result_elem == .none);
3864 } else if (ret_is_by_ref) {
3865 const result_elem_ptr = try fg.ptraddConst(result, index * ret_ty.abiSize(zcu));
3866 try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal);
3867 } else if (vector_len) |_| {
3868 result = try fg.wip.insertElement(result, result_elem, index_value, "elementwise.result");
3869 } else {
3870 assert(result == .none);
3871 result = result_elem;
3872 }
38493873 }
38503874 return result;
38513875}
......@@ -3853,19 +3877,18 @@ fn buildElementwiseCall(
38533877/// Creates a floating point comparison by lowering to the appropriate
38543878/// hardware instruction or softfloat routine for the target
38553879fn buildFloatCmp(
3856 self: *FuncGen,
3880 fg: *FuncGen,
38573881 fast: Builder.FastMathKind,
38583882 pred: math.CompareOperator,
38593883 ty: Type,
38603884 params: [2]Builder.Value,
38613885) Allocator.Error!Builder.Value {
3862 const o = self.object;
3886 const o = fg.object;
38633887 const zcu = o.zcu;
38643888 const target = zcu.getTarget();
38653889 const scalar_ty = ty.scalarType(zcu);
3866 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
38673890
3868 if (intrinsicsAllowed(scalar_ty, target)) {
3891 if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) {
38693892 const cond: Builder.FloatCondition = switch (pred) {
38703893 .eq => .oeq,
38713894 .neq => .une,
......@@ -3874,53 +3897,33 @@ fn buildFloatCmp(
38743897 .gt => .ogt,
38753898 .gte => .oge,
38763899 };
3877 return self.wip.fcmp(fast, cond, params[0], params[1], "");
3900 return fg.wip.fcmp(fast, cond, params[0], params[1], "");
38783901 }
38793902
3880 const float_bits = scalar_ty.floatBits(target);
3881 const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits);
3882 const fn_base_name = switch (pred) {
3883 .neq => "ne",
3884 .eq => "eq",
3885 .lt => "lt",
3886 .lte => "le",
3887 .gt => "gt",
3888 .gte => "ge",
3889 };
3890 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });
3891
3892 const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
3893
3894 const int_cond: Builder.IntegerCondition = switch (pred) {
3903 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{
3904 switch (pred) {
3905 .neq => "ne",
3906 .eq => "eq",
3907 .lt => "lt",
3908 .lte => "le",
3909 .gt => "gt",
3910 .gte => "ge",
3911 },
3912 compilerRtFloatAbbrev(target, scalar_ty.floatBits(target)),
3913 });
3914 const result = try fg.buildElementwiseCall(fn_name, .{
3915 .cc = target.cCallingConvention().?,
3916 .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() },
3917 .return_type = .i32_type,
3918 }, &params, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null);
3919 return fg.wip.icmp(switch (pred) {
38953920 .eq => .eq,
38963921 .neq => .ne,
38973922 .lt => .slt,
38983923 .lte => .sle,
38993924 .gt => .sgt,
39003925 .gte => .sge,
3901 };
3902
3903 if (ty.zigTypeTag(zcu) == .vector) {
3904 const vec_len = ty.vectorLen(zcu);
3905 const vector_result_ty = try o.builder.vectorType(.normal, vec_len, .i32);
3906
3907 const init = try o.builder.poisonValue(vector_result_ty);
3908 const result = try self.buildElementwiseCall(libc_fn, &params, init, vec_len);
3909
3910 const zero_vector = try o.builder.splatValue(vector_result_ty, .@"0");
3911 return self.wip.icmp(int_cond, result, zero_vector, "");
3912 }
3913
3914 const result = try self.wip.call(
3915 .normal,
3916 .ccc,
3917 .none,
3918 libc_fn.typeOf(&o.builder),
3919 libc_fn.toValue(&o.builder),
3920 &params,
3921 "",
3922 );
3923 return self.wip.icmp(int_cond, result, .@"0", "");
3926 }, result, try o.builder.splatValue(result.typeOfWip(&fg.wip), .@"0"), "");
39243927}
39253928
39263929const FloatOp = enum {
......@@ -3949,32 +3952,30 @@ const FloatOp = enum {
39493952 trunc,
39503953};
39513954
3952const FloatOpStrat = union(enum) {
3953 intrinsic: []const u8,
3954 libc: Builder.String,
3955};
3956
39573955/// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.)
39583956/// by lowering to the appropriate hardware instruction or softfloat
39593957/// routine for the target
39603958fn buildFloatOp(
3961 self: *FuncGen,
3959 fg: *FuncGen,
39623960 comptime op: FloatOp,
39633961 fast: Builder.FastMathKind,
39643962 ty: Type,
39653963 comptime params_len: usize,
39663964 params: [params_len]Builder.Value,
39673965) Allocator.Error!Builder.Value {
3968 const o = self.object;
3966 const o = fg.object;
39693967 const zcu = o.zcu;
39703968 const target = zcu.getTarget();
39713969 const scalar_ty = ty.scalarType(zcu);
3972 const llvm_ty = try o.lowerType(ty, .by_value);
39733970
3974 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
3971 switch (op) {
39753972 // Some operations are dedicated LLVM instructions, not available as intrinsics
3976 .neg => return self.wip.un(.fneg, params[0], ""),
3977 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {
3973 .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""),
3974 .add, .sub, .mul, .div, .fmod => if (intrinsicsAllowed(switch (op) {
3975 else => unreachable,
3976 .add, .sub, .mul, .div => .compiler_rt,
3977 .fmod => .libc,
3978 }, scalar_ty, target)) return fg.wip.bin(switch (fast) {
39783979 .normal => switch (op) {
39793980 .add => .fadd,
39803981 .sub => .fsub,
......@@ -3992,6 +3993,7 @@ fn buildFloatOp(
39923993 else => unreachable,
39933994 },
39943995 }, params[0], params[1], ""),
3996 .fma,
39953997 .fmax,
39963998 .fmin,
39973999 .ceil,
......@@ -4006,9 +4008,10 @@ fn buildFloatOp(
40064008 .round,
40074009 .sin,
40084010 .sqrt,
4011 .tan,
40094012 .trunc,
4010 .fma,
4011 => return self.wip.callIntrinsic(fast, .none, switch (op) {
4013 => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) {
4014 .fma => .fma,
40124015 .fmax => .maxnum,
40134016 .fmin => .minnum,
40144017 .ceil => .ceil,
......@@ -4023,39 +4026,154 @@ fn buildFloatOp(
40234026 .round => .round,
40244027 .sin => .sin,
40254028 .sqrt => .sqrt,
4029 .tan => .tan,
40264030 .trunc => .trunc,
4027 .fma => .fma,
40284031 else => unreachable,
4029 }, &.{llvm_ty}, &params, ""),
4030 .tan => unreachable,
4031 };
4032 }, &.{try o.lowerType(ty, .as_value)}, &params, ""),
4033 }
40324034
40334035 const float_bits = scalar_ty.floatBits(target);
40344036 const fn_name = switch (op) {
4035 .neg => {
4036 // In this case we can generate a softfloat negation by XORing the
4037 // bits with a constant.
4037 // In these cases we can generate a softfloat operation by modifying the sign bit using a bitwise operation.
4038 .neg, .fabs => if (isByRef(scalar_ty, zcu)) {
4039 const is_vector = ty.toIntern() != scalar_ty.toIntern();
4040 const result_ptr = try fg.buildZigAlloca(ty, .none);
4041 const entry_block = fg.wip.cursor.block;
4042 const loop_block, const done_block, const llvm_usize_ty, const offset, const elem, const result_elem = if (is_vector) loop: {
4043 const loop_block = try fg.wip.block(2, "neg_fabs.loop");
4044 const done_block = try fg.wip.block(1, "neg_fabs.done");
4045 _ = try fg.wip.br(loop_block);
4046
4047 fg.wip.cursor = .{ .block = loop_block };
4048 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
4049 const offset = try fg.wip.phi(llvm_usize_ty, "neg_fabs.offset");
4050 break :loop .{
4051 loop_block,
4052 done_block,
4053 llvm_usize_ty,
4054 offset,
4055 try fg.ptraddScaled(params[0], offset.toValue(), 1),
4056 try fg.ptraddScaled(result_ptr, offset.toValue(), 1),
4057 };
4058 } else .{ undefined, undefined, undefined, undefined, params[0], result_ptr };
4059 switch (scalar_ty.floatBits(target)) {
4060 else => unreachable,
4061 80 => {
4062 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4063 const mantissa = try fg.load(
4064 try fg.ptraddConst(elem, f80_layout.mantissa_offset),
4065 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4066 .u64,
4067 .normal,
4068 );
4069 const exponent = try fg.load(
4070 try fg.ptraddConst(elem, f80_layout.exponent_offset),
4071 f80_layout.alignment.offset(f80_layout.exponent_offset),
4072 .u16,
4073 .normal,
4074 );
4075 const exponent_sign_bit: u16 = 1 << (16 - 1);
4076 const updated_exponent = try fg.wip.bin(switch (op) {
4077 else => unreachable,
4078 .neg => .xor,
4079 .fabs => .@"and",
4080 }, exponent, try o.builder.intValue(.i16, switch (op) {
4081 else => unreachable,
4082 .neg => exponent_sign_bit,
4083 .fabs => exponent_sign_bit - 1,
4084 }), "neg_fabs.updated_exponent");
4085 try fg.store(
4086 try fg.ptraddConst(result_elem, f80_layout.mantissa_offset),
4087 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4088 mantissa,
4089 .u64,
4090 .normal,
4091 );
4092 try fg.store(
4093 try fg.ptraddConst(result_elem, f80_layout.exponent_offset),
4094 f80_layout.alignment.offset(f80_layout.exponent_offset),
4095 updated_exponent,
4096 .u16,
4097 .normal,
4098 );
4099 },
4100 128 => {
4101 const f128_layout = o.softF128Layout(.{}) catch unreachable;
4102 const lo = try fg.load(
4103 try fg.ptraddConst(elem, f128_layout.lo_offset),
4104 f128_layout.alignment.offset(f128_layout.lo_offset),
4105 .u64,
4106 .normal,
4107 );
4108 const hi = try fg.load(
4109 try fg.ptraddConst(elem, f128_layout.hi_offset),
4110 f128_layout.alignment.offset(f128_layout.hi_offset),
4111 .u64,
4112 .normal,
4113 );
4114 const hi_sign_bit: u64 = 1 << (64 - 1);
4115 const updated_hi = try fg.wip.bin(switch (op) {
4116 else => unreachable,
4117 .neg => .xor,
4118 .fabs => .@"and",
4119 }, hi, try o.builder.intValue(.i64, switch (op) {
4120 else => unreachable,
4121 .neg => hi_sign_bit,
4122 .fabs => hi_sign_bit - 1,
4123 }), "neg_fabs.updated_hi");
4124 try fg.store(
4125 try fg.ptraddConst(result_elem, f128_layout.lo_offset),
4126 f128_layout.alignment.offset(f128_layout.lo_offset),
4127 lo,
4128 .u64,
4129 .normal,
4130 );
4131 try fg.store(
4132 try fg.ptraddConst(result_elem, f128_layout.hi_offset),
4133 f128_layout.alignment.offset(f128_layout.hi_offset),
4134 updated_hi,
4135 .u64,
4136 .normal,
4137 );
4138 },
4139 }
4140 if (is_vector) {
4141 const next_offset = try fg.wip.bin(.@"add nuw", offset.toValue(), try o.builder.intValue(llvm_usize_ty, scalar_ty.abiSize(zcu)), "neg_fabs.next_offset");
4142 offset.finish(&.{ try o.builder.intValue(llvm_usize_ty, 0), next_offset }, &.{ entry_block, loop_block }, &fg.wip);
4143 const is_done = try fg.wip.icmp(.eq, next_offset, try o.builder.intValue(llvm_usize_ty, ty.abiSize(zcu)), "neg_fabs.is_done");
4144 _ = try fg.wip.brCond(is_done, done_block, loop_block, .none);
4145
4146 fg.wip.cursor = .{ .block = done_block };
4147 }
4148 return result_ptr;
4149 } else {
40384150 const int_ty = try o.builder.intType(@intCast(float_bits));
40394151 const cast_ty = switch (ty.zigTypeTag(zcu)) {
40404152 .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty),
40414153 else => int_ty,
40424154 };
4043 const sign_mask = try o.builder.splatValue(
4044 cast_ty,
4045 try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)),
4046 );
4047 const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");
4048 const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");
4049 return self.wip.cast(.bitcast, result, llvm_ty, "");
4155 const sign_bit = @as(u128, 1) << @intCast(float_bits - 1);
4156 const bitwise_rhs = try o.builder.splatValue(cast_ty, try o.builder.intConst(int_ty, switch (op) {
4157 else => unreachable,
4158 .neg => sign_bit,
4159 .fabs => sign_bit - 1,
4160 }));
4161 const bitcasted_operand = try fg.wip.cast(.bitcast, params[0], cast_ty, "");
4162 const result = try fg.wip.bin(switch (op) {
4163 else => unreachable,
4164 .neg => .xor,
4165 .fabs => .@"and",
4166 }, bitcasted_operand, bitwise_rhs, "");
4167 const llvm_ty = try o.lowerType(ty, .as_value);
4168 return fg.wip.cast(.bitcast, result, llvm_ty, "");
40504169 },
40514170 .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{
4052 @tagName(op), compilerRtFloatAbbrev(float_bits),
4171 @tagName(op), compilerRtFloatAbbrev(target, float_bits),
40534172 }),
40544173 .ceil,
40554174 .cos,
40564175 .exp,
40574176 .exp2,
4058 .fabs,
40594177 .floor,
40604178 .fma,
40614179 .fmax,
......@@ -4073,27 +4191,27 @@ fn buildFloatOp(
40734191 libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),
40744192 }),
40754193 };
4194 return fg.buildElementwiseCall(fn_name, .{
4195 .cc = target.cCallingConvention().?,
4196 .param_types = &@as([params_len]InternPool.Index, @splat(scalar_ty.toIntern())),
4197 .return_type = scalar_ty.toIntern(),
4198 }, &params, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null);
4199}
40764200
4077 const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
4078 const libc_fn = try o.getLibcFunction(
4079 fn_name,
4080 @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len],
4081 scalar_llvm_ty,
4082 );
4083 if (ty.zigTypeTag(zcu) == .vector) {
4084 const result = try o.builder.poisonValue(llvm_ty);
4085 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(zcu));
4086 }
4087
4088 return self.wip.call(
4089 fast.toCallKind(),
4090 .ccc,
4091 .none,
4092 libc_fn.typeOf(&o.builder),
4093 libc_fn.toValue(&o.builder),
4094 &params,
4095 "",
4096 );
4201/// Creates a floating point cast operation by lowering to the specified softfloat routine.
4202fn buildFloatCastCall(
4203 fg: *FuncGen,
4204 dest_ty: Type,
4205 fn_name: Builder.StrtabString,
4206 operand_ty: Type,
4207 operand: Builder.Value,
4208) Allocator.Error!Builder.Value {
4209 const zcu = fg.object.zcu;
4210 return fg.buildElementwiseCall(fn_name, .{
4211 .cc = zcu.getTarget().cCallingConvention().?,
4212 .param_types = &.{operand_ty.scalarType(zcu).toIntern()},
4213 .return_type = dest_ty.scalarType(zcu).toIntern(),
4214 }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null);
40974215}
40984216
40994217fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -4129,7 +4247,7 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
41294247 const dest_ty = self.typeOfIndex(inst);
41304248 assert(isByRef(dest_ty, zcu)); // auto structs are by-ref
41314249
4132 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4250 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
41334251
41344252 const result = try self.wip.bin(.shl, lhs, casted_rhs, "");
41354253 const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
......@@ -4196,7 +4314,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
41964314 }
41974315 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
41984316
4199 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4317 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
42004318 return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
42014319 .@"shl nsw"
42024320 else
......@@ -4217,7 +4335,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
42174335 // features which we do not use. Therefore this branch is currently impossible.
42184336 unreachable;
42194337 }
4220 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4338 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
42214339 return self.wip.bin(.shl, lhs, casted_rhs, "");
42224340}
42234341
......@@ -4231,8 +4349,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
42314349
42324350 const lhs_ty = self.typeOf(bin_op.lhs);
42334351 const lhs_info = lhs_ty.intInfo(zcu);
4234 const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);
4235 const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value);
4352 const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value);
4353 const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .as_value);
42364354
42374355 const rhs_ty = self.typeOf(bin_op.rhs);
42384356 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) {
......@@ -4242,8 +4360,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
42424360 }
42434361 const rhs_info = rhs_ty.intInfo(zcu);
42444362 assert(rhs_info.signedness == .unsigned);
4245 const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value);
4246 const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value);
4363 const llvm_rhs_ty = try o.lowerType(rhs_ty, .as_value);
4364 const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .as_value);
42474365
42484366 const result = try self.wip.callIntrinsic(
42494367 .normal,
......@@ -4319,7 +4437,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!
43194437 }
43204438 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
43214439
4322 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
4440 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), "");
43234441 const is_signed_int = lhs_scalar_ty.isSignedInt(zcu);
43244442
43254443 return self.wip.bin(if (is_exact)
......@@ -4340,7 +4458,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
43404458 .normal,
43414459 .none,
43424460 .abs,
4343 &.{try o.lowerType(operand_ty, .by_value)},
4461 &.{try o.lowerType(operand_ty, .as_value)},
43444462 &.{ operand, .false },
43454463 "",
43464464 ),
......@@ -4354,7 +4472,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
43544472 const zcu = o.zcu;
43554473 const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
43564474 const dest_ty = fg.typeOfIndex(inst);
4357 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
4475 const dest_llvm_ty = try o.lowerType(dest_ty, .as_value);
43584476 const operand = try fg.resolveInst(ty_op.operand);
43594477 const operand_ty = fg.typeOf(ty_op.operand);
43604478 const operand_info = operand_ty.intInfo(zcu);
......@@ -4382,8 +4500,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
43824500
43834501 if (!have_min_check and !have_max_check) break :bounds_check;
43844502
4385 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
4386 const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value);
4503 const operand_llvm_ty = try o.lowerType(operand_ty, .as_value);
4504 const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .as_value);
43874505
43884506 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
43894507 assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector));
......@@ -4461,7 +4579,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
44614579fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
44624580 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
44634581 const operand = try self.resolveInst(ty_op.operand);
4464 const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .by_value);
4582 const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .as_value);
44654583 return self.wip.cast(.trunc, operand, dest_llvm_ty, "");
44664584}
44674585
......@@ -4471,32 +4589,20 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
44714589 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
44724590 const operand = try self.resolveInst(ty_op.operand);
44734591 const operand_ty = self.typeOf(ty_op.operand);
4592 const operand_scalar_ty = operand_ty.scalarType(zcu);
44744593 const dest_ty = self.typeOfIndex(inst);
4594 const dest_scalar_ty = dest_ty.scalarType(zcu);
44754595 const target = zcu.getTarget();
44764596
4477 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
4478 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), "");
4479 } else {
4480 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
4481 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
4482
4483 const dest_bits = dest_ty.floatBits(target);
4484 const src_bits = operand_ty.floatBits(target);
4485 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
4486 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
4487 });
4488
4489 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty);
4490 return self.wip.call(
4491 .normal,
4492 .ccc,
4493 .none,
4494 libc_fn.typeOf(&o.builder),
4495 libc_fn.toValue(&o.builder),
4496 &.{operand},
4497 "",
4498 );
4499 }
4597 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4598 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
4599 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), "");
4600 const dest_bits = dest_scalar_ty.floatBits(target);
4601 const src_bits = operand_scalar_ty.floatBits(target);
4602 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
4603 compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits),
4604 });
4605 return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand);
45004606}
45014607
45024608fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -4505,38 +4611,20 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
45054611 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
45064612 const operand = try self.resolveInst(ty_op.operand);
45074613 const operand_ty = self.typeOf(ty_op.operand);
4614 const operand_scalar_ty = operand_ty.scalarType(zcu);
45084615 const dest_ty = self.typeOfIndex(inst);
4616 const dest_scalar_ty = dest_ty.scalarType(zcu);
45094617 const target = zcu.getTarget();
45104618
4511 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
4512 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), "");
4513 } else {
4514 const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
4515 const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
4516
4517 const dest_bits = dest_ty.scalarType(zcu).floatBits(target);
4518 const src_bits = operand_ty.scalarType(zcu).floatBits(target);
4519 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{
4520 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
4521 });
4522
4523 const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty);
4524 if (dest_ty.isVector(zcu)) return self.buildElementwiseCall(
4525 libc_fn,
4526 &.{operand},
4527 try o.builder.poisonValue(dest_llvm_ty),
4528 dest_ty.vectorLen(zcu),
4529 );
4530 return self.wip.call(
4531 .normal,
4532 .ccc,
4533 .none,
4534 libc_fn.typeOf(&o.builder),
4535 libc_fn.toValue(&o.builder),
4536 &.{operand},
4537 "",
4538 );
4539 }
4619 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4620 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
4621 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), "");
4622 const dest_bits = dest_scalar_ty.floatBits(target);
4623 const src_bits = operand_scalar_ty.floatBits(target);
4624 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{
4625 compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits),
4626 });
4627 return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand);
45404628}
45414629
45424630fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value {
......@@ -4558,28 +4646,161 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
45584646 // * bool/int/float <-> bool/int/float
45594647 // * `@Vector(n, A)` <-> `@Vector(n, B)`
45604648 //
4561 // All of these cases can be handled by LLVM's `bitcast` instruction.
4649 // Most of these cases can be handled by LLVM's `bitcast` instruction, except when
4650 // a non-native type like `f80` is used.
45624651
4563 assert(!isByRef(operand_ty, zcu));
4564 assert(!isByRef(dest_ty, zcu));
4652 if (isByRef(operand_ty, zcu)) {
4653 const operand_scalar_ty = operand_ty.scalarType(zcu);
4654 const target = zcu.getTarget();
4655 const bits = operand_scalar_ty.floatBits(target);
4656 const dest_scalar_ty = dest_ty.scalarType(zcu);
4657 if (isByRef(dest_ty, zcu)) {
4658 assert(dest_scalar_ty.floatBits(target) == bits);
4659 return operand;
4660 }
4661 assert(dest_scalar_ty.intInfo(zcu).bits == bits);
45654662
4566 const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
4567 const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, "");
4568 if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) {
4569 const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty);
4570 const is_valid_enum_val = try fg.wip.call(
4571 .normal,
4572 .fastcc,
4573 .none,
4574 llvm_fn.typeOf(&o.builder),
4575 llvm_fn.toValue(&o.builder),
4576 &.{result},
4577 "",
4578 );
4579 const fail_block = try fg.wip.block(1, "ValidEnumFail");
4580 const ok_block = try fg.wip.block(1, "ValidEnumOk");
4581 _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none);
4582 fg.wip.cursor = .{ .block = fail_block };
4663 const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern())
4664 operand_ty.vectorLen(zcu)
4665 else
4666 null;
4667 const operand_scalar_size = operand_scalar_ty.abiSize(zcu);
4668 var result = if (len) |_|
4669 try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value))
4670 else
4671 undefined;
4672 for (0..len orelse 1) |index| {
4673 const result_elem = result_elem: switch (bits) {
4674 else => unreachable,
4675 80 => {
4676 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4677 const mantissa = try fg.load(
4678 try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.mantissa_offset),
4679 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4680 .u64,
4681 .normal,
4682 );
4683 const exponent = try fg.load(
4684 try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.exponent_offset),
4685 f80_layout.alignment.offset(f80_layout.exponent_offset),
4686 .u16,
4687 .normal,
4688 );
4689 const casted_mantissa = try fg.wip.cast(.zext, mantissa, .i80, "bitCast.casted_mantissa");
4690 const casted_exponent = try fg.wip.cast(.zext, exponent, .i80, "bitCast.casted_exponent");
4691 const shifted_exponent = try fg.wip.bin(.@"shl nuw", casted_exponent, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent");
4692 break :result_elem try fg.wip.bin(.@"or", casted_mantissa, shifted_exponent, "bitCast.result_elem");
4693 },
4694 128 => {
4695 const f128_layout = o.softF128Layout(.{}) catch unreachable;
4696 const lo = try fg.load(
4697 try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.lo_offset),
4698 f128_layout.alignment.offset(f128_layout.lo_offset),
4699 .u64,
4700 .normal,
4701 );
4702 const hi = try fg.load(
4703 try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.hi_offset),
4704 f128_layout.alignment.offset(f128_layout.hi_offset),
4705 .u64,
4706 .normal,
4707 );
4708 const casted_lo = try fg.wip.cast(.zext, lo, .i128, "bitCast.casted_lo");
4709 const casted_hi = try fg.wip.cast(.zext, hi, .i128, "bitCast.casted_hi");
4710 const shifted_hi = try fg.wip.bin(.@"shl nuw", casted_hi, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi");
4711 break :result_elem try fg.wip.bin(.@"or", casted_lo, shifted_hi, "bitCast.result_elem");
4712 },
4713 };
4714 result = if (len) |_|
4715 try fg.wip.insertElement(result, result_elem, try o.builder.intValue(.i32, index), "elementwise.result")
4716 else
4717 result_elem;
4718 }
4719 return result;
4720 }
4721
4722 if (isByRef(dest_ty, zcu)) {
4723 const dest_scalar_ty = dest_ty.scalarType(zcu);
4724 const bits = dest_scalar_ty.floatBits(zcu.getTarget());
4725 assert(dest_scalar_ty.isRuntimeFloat());
4726 const operand_scalar_ty = operand_ty.scalarType(zcu);
4727 assert(operand_scalar_ty.intInfo(zcu).bits == bits);
4728
4729 const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern())
4730 operand_ty.vectorLen(zcu)
4731 else
4732 null;
4733 const operand_scalar_size = operand_scalar_ty.abiSize(zcu);
4734 const result_ptr = try fg.buildZigAlloca(dest_ty, .none);
4735 for (0..len orelse 1) |index| {
4736 const operand_elem = if (len) |_|
4737 try fg.wip.extractElement(operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem")
4738 else
4739 operand;
4740 switch (bits) {
4741 else => unreachable,
4742 80 => {
4743 const f80_layout = o.softF80Layout(.{}) catch unreachable;
4744 const mantissa = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.mantissa");
4745 const shifted_exponent = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent");
4746 const exponent = try fg.wip.cast(.@"trunc nuw", shifted_exponent, .i16, "bitCast.exponent");
4747 try fg.store(
4748 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.mantissa_offset),
4749 f80_layout.alignment.offset(f80_layout.mantissa_offset),
4750 mantissa,
4751 .u64,
4752 .normal,
4753 );
4754 try fg.store(
4755 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.exponent_offset),
4756 f80_layout.alignment.offset(f80_layout.exponent_offset),
4757 exponent,
4758 .u16,
4759 .normal,
4760 );
4761 },
4762 128 => {
4763 const f128_layout = o.softF128Layout(.{}) catch unreachable;
4764 const lo = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.lo");
4765 const shifted_hi = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi");
4766 const hi = try fg.wip.cast(.@"trunc nuw", shifted_hi, .i64, "bitCast.hi");
4767 try fg.store(
4768 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.lo_offset),
4769 f128_layout.alignment.offset(f128_layout.lo_offset),
4770 lo,
4771 .u64,
4772 .normal,
4773 );
4774 try fg.store(
4775 try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.hi_offset),
4776 f128_layout.alignment.offset(f128_layout.hi_offset),
4777 hi,
4778 .u64,
4779 .normal,
4780 );
4781 },
4782 }
4783 }
4784 return result_ptr;
4785 }
4786
4787 const llvm_dest_ty = try o.lowerType(dest_ty, .as_value);
4788 const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, "");
4789 if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) {
4790 const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty);
4791 const is_valid_enum_val = try fg.wip.call(
4792 .normal,
4793 .fastcc,
4794 .none,
4795 llvm_fn.typeOf(&o.builder),
4796 llvm_fn.toValue(&o.builder),
4797 &.{result},
4798 "",
4799 );
4800 const fail_block = try fg.wip.block(1, "ValidEnumFail");
4801 const ok_block = try fg.wip.block(1, "ValidEnumOk");
4802 _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none);
4803 fg.wip.cursor = .{ .block = fail_block };
45834804 try fg.buildSimplePanic(.invalid_enum_value);
45844805 fg.wip.cursor = .{ .block = ok_block };
45854806 }
......@@ -4606,7 +4827,7 @@ fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
46064827 assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu));
46074828
46084829 const operand = try fg.resolveInst(ty_op.operand);
4609 const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
4830 const llvm_dest_ty = try o.lowerType(dest_ty, .as_value);
46104831 return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
46114832}
46124833
......@@ -4620,7 +4841,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
46204841 assert(dest_ty.scalarType(zcu).toIntern() == .usize_type);
46214842
46224843 const operand = try fg.resolveInst(ty_op.operand);
4623 const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
4844 const llvm_dest_ty = try o.lowerType(dest_ty, .as_value);
46244845 return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
46254846}
46264847
......@@ -4730,7 +4951,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
47304951 const ptr_align = ptr_ty.ptrAlignment(zcu);
47314952 const elem_ty = ptr_ty.childType(zcu);
47324953 if (!elem_ty.hasRuntimeBits(zcu)) {
4733 return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue();
4954 return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue();
47344955 }
47354956 return self.buildZigAlloca(elem_ty, ptr_align);
47364957}
......@@ -4743,7 +4964,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
47434964 const ptr_align = ptr_ty.ptrAlignment(zcu);
47444965 const elem_ty = ptr_ty.childType(zcu);
47454966 if (!elem_ty.hasRuntimeBits(zcu)) {
4746 return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue();
4967 return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue();
47474968 }
47484969 return self.buildZigAlloca(elem_ty, ptr_align);
47494970}
......@@ -4754,10 +4975,7 @@ fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Alloca
47544975 .none => ty.abiAlignment(o.zcu),
47554976 else => |a| a,
47564977 };
4757 return fg.buildAlloca(
4758 try o.lowerType(ty, .in_memory),
4759 resolved_align.toLlvm(),
4760 );
4978 return fg.buildAlloca(try o.lowerType(ty, .in_memory), resolved_align.toLlvm());
47614979}
47624980
47634981/// Unlike `WipFunction.alloca`, this puts the alloca instruction at the top of the function.
......@@ -4832,7 +5050,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
48325050 return .none;
48335051 }
48345052
4835 const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), elem_ty.abiSize(zcu));
5053 const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), elem_ty.abiSize(zcu));
48365054 _ = try fg.wip.callMemSet(
48375055 ptr,
48385056 ptr_alignment.toLlvm(),
......@@ -4850,24 +5068,31 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu
48505068 const elem = try fg.resolveInst(bin_op.rhs);
48515069
48525070 if (ptr_info.flags.vector_index != .none) {
4853 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4854 const vec_ty = try fg.pt.vectorType(.{
4855 .len = ptr_info.packed_offset.host_size,
4856 .child = elem_ty.toIntern(),
4857 });
5071 if (isByRef(elem_ty, zcu)) {
5072 const offset = @backingInt(ptr_info.flags.vector_index) * elem_ty.abiSize(zcu);
5073 const elem_ptr = try fg.ptraddConst(ptr, offset);
5074 try fg.store(elem_ptr, ptr_alignment.offset(offset), elem, elem_ty, access_kind);
5075 } else {
5076 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
5077 const vec_ty = try fg.pt.vectorType(.{
5078 .len = ptr_info.packed_offset.host_size,
5079 .child = elem_ty.toIntern(),
5080 });
5081
5082 const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind);
5083 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
5084 const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, "");
48585085
4859 const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind);
4860 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
4861 const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, "");
5086 try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
5087 }
48625088
4863 try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
48645089 return .none;
48655090 }
48665091
48675092 if (ptr_info.packed_offset.host_size != 0) {
48685093 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
48695094 const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));
4870 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value);
5095 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value);
48715096
48725097 const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind);
48735098
......@@ -4927,32 +5152,98 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
49275152 if (ptr_info.flags.is_volatile) .@"volatile" else .normal;
49285153
49295154 if (ptr_info.flags.vector_index != .none) {
4930 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
4931 const vec_ty = try fg.pt.vectorType(.{
4932 .len = ptr_info.packed_offset.host_size,
4933 .child = elem_ty.toIntern(),
4934 });
4935 const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind);
4936 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
4937 return fg.wip.extractElement(vector_val, index_val, "");
5155 if (isByRef(elem_ty, zcu)) {
5156 const elem_size = elem_ty.abiSize(zcu);
5157 const offset = @backingInt(ptr_info.flags.vector_index) * elem_size;
5158 const elem_ptr = try fg.ptraddConst(ptr, offset);
5159 return fg.load(elem_ptr, ptr_align.offset(offset), elem_ty, access_kind);
5160 } else {
5161 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
5162 const vec_ty = try fg.pt.vectorType(.{
5163 .len = ptr_info.packed_offset.host_size,
5164 .child = elem_ty.toIntern(),
5165 });
5166 const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind);
5167 const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
5168 return fg.wip.extractElement(vector_val, index_val, "");
5169 }
49385170 }
49395171
49405172 if (ptr_info.packed_offset.host_size == 0) {
49415173 return fg.load(ptr, ptr_align, elem_ty, access_kind);
49425174 }
49435175
4944 assert(!isByRef(elem_ty, zcu)); // all packable types are by-val
4945
49465176 // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
49475177 const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));
4948 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value);
5178 const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value);
49495179
49505180 const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal);
49515181
49525182 const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);
49535183 const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset);
49545184 const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, "");
4955 const elem_llvm_ty = try o.lowerType(elem_ty, .by_value);
5185
5186 if (isByRef(elem_ty, zcu)) {
5187 const result_ptr = try fg.buildZigAlloca(elem_ty, .none);
5188 switch (elem_ty.floatBits(zcu.getTarget())) {
5189 else => unreachable,
5190 80 => {
5191 const f80_layout = o.softF80Layout(.{}) catch unreachable;
5192 const mantissa = try fg.wip.cast(.trunc, shifted_value, .i64, "load.mantissa");
5193 const shifted_exponent = try fg.wip.bin(
5194 .lshr,
5195 backing_int_val,
5196 try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64),
5197 "load.shifted_exponent",
5198 );
5199 const exponent = try fg.wip.cast(.trunc, shifted_exponent, .i16, "load.exponent");
5200
5201 try fg.store(
5202 try fg.ptraddConst(result_ptr, f80_layout.mantissa_offset),
5203 f80_layout.alignment.offset(f80_layout.mantissa_offset),
5204 mantissa,
5205 .u64,
5206 .normal,
5207 );
5208 try fg.store(
5209 try fg.ptraddConst(result_ptr, f80_layout.exponent_offset),
5210 f80_layout.alignment.offset(f80_layout.exponent_offset),
5211 exponent,
5212 .u16,
5213 .normal,
5214 );
5215 },
5216 128 => {
5217 const f128_layout = o.softF128Layout(.{}) catch unreachable;
5218 const lo = try fg.wip.cast(.trunc, shifted_value, .i64, "load.lo");
5219 const shifted_hi = try fg.wip.bin(
5220 .lshr,
5221 backing_int_val,
5222 try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64),
5223 "load.shifted_hi",
5224 );
5225 const hi = try fg.wip.cast(.trunc, shifted_hi, .i64, "load.hi");
5226
5227 try fg.store(
5228 try fg.ptraddConst(result_ptr, f128_layout.lo_offset),
5229 f128_layout.alignment.offset(f128_layout.lo_offset),
5230 lo,
5231 .u64,
5232 .normal,
5233 );
5234 try fg.store(
5235 try fg.ptraddConst(result_ptr, f128_layout.hi_offset),
5236 f128_layout.alignment.offset(f128_layout.hi_offset),
5237 hi,
5238 .u64,
5239 .normal,
5240 );
5241 },
5242 }
5243 return result_ptr;
5244 }
5245
5246 const elem_llvm_ty = try o.lowerType(elem_ty, .as_value);
49565247
49575248 if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) {
49585249 const same_size_int = try o.builder.intType(@intCast(elem_bits));
......@@ -5002,7 +5293,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
50025293fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
50035294 _ = inst;
50045295 const o = self.object;
5005 const llvm_usize = try o.lowerType(.usize, .by_value);
5296 const llvm_usize = try o.lowerType(.usize, .as_value);
50065297 if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) {
50075298 // https://github.com/ziglang/zig/issues/11946
50085299 return o.builder.intValue(llvm_usize, 0);
......@@ -5014,7 +5305,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
50145305fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
50155306 _ = inst;
50165307 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, "");
5017 return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .by_value), "");
5308 return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .as_value), "");
50185309}
50195310
50205311fn airCmpxchg(
......@@ -5031,7 +5322,7 @@ fn airCmpxchg(
50315322 var expected_value = try self.resolveInst(extra.expected_value);
50325323 var new_value = try self.resolveInst(extra.new_value);
50335324 const operand_ty = ptr_ty.childType(zcu);
5034 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5325 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
50355326 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false);
50365327 if (llvm_abi_ty != .none) {
50375328 // operand needs widening and truncating
......@@ -5101,7 +5392,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
51015392 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
51025393 const ordering = toLlvmAtomicOrdering(extra.ordering());
51035394 const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg);
5104 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5395 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
51055396
51065397 const access_kind: Builder.MemoryAccessKind =
51075398 if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
......@@ -5130,7 +5421,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
51305421
51315422 // If we are storing a pointer we need to convert to and from a plain old integer.
51325423 const non_ptr_operand = switch (operand_ty.zigTypeTag(zcu)) {
5133 .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .by_value), ""),
5424 .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .as_value), ""),
51345425 else => operand,
51355426 };
51365427
......@@ -5169,7 +5460,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
51695460 Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm();
51705461 const access_kind: Builder.MemoryAccessKind =
51715462 if (info.flags.is_volatile) .@"volatile" else .normal;
5172 const elem_llvm_ty = try o.lowerType(elem_ty, .by_value);
5463 const elem_llvm_ty = try o.lowerType(elem_ty, .as_value);
51735464
51745465 self.maybeMarkAllowZeroAccess(info);
51755466
......@@ -5503,11 +5794,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
55035794 .normal,
55045795 .none,
55055796 intrinsic,
5506 &.{try o.lowerType(operand_ty, .by_value)},
5797 &.{try o.lowerType(operand_ty, .as_value)},
55075798 &.{ operand, .false },
55085799 "",
55095800 );
5510 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
5801 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), "");
55115802}
55125803
55135804fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value {
......@@ -5521,11 +5812,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
55215812 .normal,
55225813 .none,
55235814 intrinsic,
5524 &.{try o.lowerType(operand_ty, .by_value)},
5815 &.{try o.lowerType(operand_ty, .as_value)},
55255816 &.{operand},
55265817 "",
55275818 );
5528 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
5819 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), "");
55295820}
55305821
55315822fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -5538,7 +5829,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
55385829
55395830 const inst_ty = self.typeOfIndex(inst);
55405831 var operand = try self.resolveInst(ty_op.operand);
5541 var llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5832 var llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
55425833
55435834 if (bits % 16 == 8) {
55445835 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte
......@@ -5559,7 +5850,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
55595850
55605851 const result =
55615852 try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");
5562 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
5853 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), "");
55635854}
55645855
55655856fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -5579,7 +5870,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui
55795870
55805871 for (0..names.len) |name_index| {
55815872 const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
5582 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.by_value), err_int);
5873 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.as_value), err_int);
55835874 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
55845875 }
55855876 self.wip.cursor = .{ .block = valid_block };
......@@ -5638,7 +5929,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
56385929 const slice_ty = self.typeOfIndex(inst);
56395930
56405931 // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed.
5641 const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .by_value), "");
5932 const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .as_value), "");
56425933
56435934 const error_name_table_ptr = try o.getErrorNameTable();
56445935 const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu));
......@@ -5649,7 +5940,7 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
56495940 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
56505941 const scalar = try self.resolveInst(ty_op.operand);
56515942 const vector_ty = self.typeOfIndex(inst);
5652 return self.wip.splatVector(try self.object.lowerType(vector_ty, .by_value), scalar, "");
5943 return self.wip.splatVector(try self.object.lowerType(vector_ty, .as_value), scalar, "");
56535944}
56545945
56555946fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
......@@ -5672,9 +5963,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
56725963 const operand = try fg.resolveInst(unwrapped.operand);
56735964 const mask = unwrapped.mask;
56745965 const operand_ty = fg.typeOf(unwrapped.operand);
5675 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5676 const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value);
5677 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);
5966 const llvm_operand_ty = try o.lowerType(operand_ty, .as_value);
5967 const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .as_value);
5968 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value);
56785969 const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty);
56795970 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
56805971 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
......@@ -5704,7 +5995,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
57045995 .elem => llvm_poison_elem,
57055996 .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: {
57065997 any_defined_comptime_value = true;
5707 break :elem try o.lowerValue(val, .by_value);
5998 break :elem try o.lowerValue(val, .as_value);
57085999 } else llvm_poison_elem,
57096000 };
57106001 }
......@@ -5776,7 +6067,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
57766067 const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst);
57776068
57786069 const mask = unwrapped.mask;
5779 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);
6070 const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value);
57806071 const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
57816072 const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
57826073
......@@ -5848,95 +6139,25 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
58486139 );
58496140}
58506141
5851/// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result.
5852///
5853/// Equivalent to:
5854/// ```
5855/// var accum: T = init;
5856/// for (0..i) |i| {
5857/// accum = llvm_fn(accum, vec[i]);
5858/// }
5859/// // result is 'accum'
5860/// ```
5861fn buildReducedCall(
5862 self: *FuncGen,
5863 llvm_fn: Builder.Function.Index,
5864 operand_vector: Builder.Value,
5865 vector_len: usize,
5866 accum_init: Builder.Value,
5867) Allocator.Error!Builder.Value {
5868 const o = self.object;
5869 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
5870 const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len);
5871 const llvm_result_ty = accum_init.typeOfWip(&self.wip);
5872
5873 const entry_block = self.wip.cursor.block;
5874
5875 const cond_block = try self.wip.block(2, "ReduceLoopCond");
5876 const body_block = try self.wip.block(1, "ReduceLoopBody");
5877 const exit_block = try self.wip.block(1, "ReduceLoopExit");
5878
5879 _ = try self.wip.br(cond_block);
5880
5881 // ReduceLoopCond:
5882 // %index = phi iN [0, %Entry], [%new_index, %ReduceLoopBody]
5883 // %accum = phi T [%accum_init, %Entry], [%new_accum, %ReduceLoopBody]
5884 // %cond = icmp ult iN %index, %vector_len
5885 // br i1 %cond, label %ReduceLoopBody, label %ReduceLoopExit
5886 self.wip.cursor = .{ .block = cond_block };
5887 const index = try self.wip.phi(llvm_usize_ty, "");
5888 const accum = try self.wip.phi(llvm_result_ty, "");
5889 const cond = try self.wip.icmp(.ult, index.toValue(), llvm_vector_len, "");
5890 _ = try self.wip.brCond(cond, body_block, exit_block, .none);
5891
5892 // ReduceLoopBody:
5893 // %elem = extractelement <n x T> %operand_vec, iN %index
5894 // %new_accum = call T @llvm_fn(T %accum, T %elem)
5895 // %new_index = add nuw iN %index, 1
5896 // br label %ReduceLoopCond
5897 self.wip.cursor = .{ .block = body_block };
5898 const elem = try self.wip.extractElement(operand_vector, index.toValue(), "");
5899 const new_accum = try self.wip.call(
5900 .normal,
5901 .ccc,
5902 .none,
5903 llvm_fn.typeOf(&o.builder),
5904 llvm_fn.toValue(&o.builder),
5905 &.{ accum.toValue(), elem },
5906 "",
5907 );
5908 const new_index = try self.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(llvm_usize_ty, 1), "");
5909 _ = try self.wip.br(cond_block);
5910
5911 const index_init = try o.builder.intValue(llvm_usize_ty, 0);
5912 index.finish(&.{ index_init, new_index }, &.{ entry_block, body_block }, &self.wip);
5913 accum.finish(&.{ accum_init, new_accum }, &.{ entry_block, body_block }, &self.wip);
5914
5915 self.wip.cursor = .{ .block = exit_block };
5916 return accum.toValue();
5917}
5918
5919fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
5920 const o = self.object;
6142fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
6143 const o = fg.object;
59216144 const zcu = o.zcu;
59226145 const target = zcu.getTarget();
59236146
5924 const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce;
5925 const operand = try self.resolveInst(reduce.operand);
5926 const operand_ty = self.typeOf(reduce.operand);
5927 const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
5928 const scalar_ty = self.typeOfIndex(inst);
5929 const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value);
6147 const reduce = fg.air.instructions.items(.data)[@backingInt(inst)].reduce;
6148 const operand = try fg.resolveInst(reduce.operand);
6149 const operand_ty = fg.typeOf(reduce.operand);
6150 const scalar_ty = fg.typeOfIndex(inst);
59306151
59316152 switch (reduce.operation) {
5932 .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
6153 .And, .Or, .Xor => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
59336154 .And => .@"vector.reduce.and",
59346155 .Or => .@"vector.reduce.or",
59356156 .Xor => .@"vector.reduce.xor",
59366157 else => unreachable,
5937 }, &.{llvm_operand_ty}, &.{operand}, ""),
6158 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
59386159 .Min, .Max => switch (scalar_ty.zigTypeTag(zcu)) {
5939 .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
6160 .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
59406161 .Min => if (scalar_ty.isSignedInt(zcu))
59416162 .@"vector.reduce.smin"
59426163 else
......@@ -5946,29 +6167,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
59466167 else
59476168 .@"vector.reduce.umax",
59486169 else => unreachable,
5949 }, &.{llvm_operand_ty}, &.{operand}, ""),
5950 .float => if (intrinsicsAllowed(scalar_ty, target))
5951 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
6170 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
6171 .float => if (intrinsicsAllowed(.libc, scalar_ty, target))
6172 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
59526173 .Min => .@"vector.reduce.fmin",
59536174 .Max => .@"vector.reduce.fmax",
59546175 else => unreachable,
5955 }, &.{llvm_operand_ty}, &.{operand}, ""),
6176 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
59566177 else => unreachable,
59576178 },
59586179 .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
5959 .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
6180 .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
59606181 .Add => .@"vector.reduce.add",
59616182 .Mul => .@"vector.reduce.mul",
59626183 else => unreachable,
5963 }, &.{llvm_operand_ty}, &.{operand}, ""),
5964 .float => if (intrinsicsAllowed(scalar_ty, target))
5965 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
6184 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
6185 .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target))
6186 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
59666187 .Add => .@"vector.reduce.fadd",
59676188 .Mul => .@"vector.reduce.fmul",
59686189 else => unreachable,
5969 }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) {
5970 .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0),
5971 .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0),
6190 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{ switch (reduce.operation) {
6191 .Add => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), -0.0),
6192 .Mul => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), 1.0),
59726193 else => unreachable,
59736194 }, operand }, ""),
59746195 else => unreachable,
......@@ -5986,62 +6207,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
59866207 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
59876208 }),
59886209 .Add => try o.builder.strtabStringFmt("__add{s}f3", .{
5989 compilerRtFloatAbbrev(float_bits),
6210 compilerRtFloatAbbrev(target, float_bits),
59906211 }),
59916212 .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{
5992 compilerRtFloatAbbrev(float_bits),
6213 compilerRtFloatAbbrev(target, float_bits),
59936214 }),
59946215 else => unreachable,
59956216 };
5996
5997 const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty);
5998 const init_val = switch (llvm_scalar_ty) {
5999 .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast(
6000 @as(f16, switch (reduce.operation) {
6001 .Min, .Max => std.math.nan(f16),
6002 .Add => -0.0,
6003 .Mul => 1.0,
6004 else => unreachable,
6005 }),
6006 ))),
6007 .i80 => try o.builder.intValue(.i80, @as(i80, @bitCast(
6008 @as(f80, switch (reduce.operation) {
6009 .Min, .Max => std.math.nan(f80),
6010 .Add => -0.0,
6011 .Mul => 1.0,
6012 else => unreachable,
6013 }),
6014 ))),
6015 .i128 => try o.builder.intValue(.i128, @as(i128, @bitCast(
6016 @as(f128, switch (reduce.operation) {
6017 .Min, .Max => std.math.nan(f128),
6018 .Add => -0.0,
6019 .Mul => 1.0,
6020 else => unreachable,
6021 }),
6022 ))),
6217 const fn_info: Object.FuncInfo = .{
6218 .cc = target.cCallingConvention().?,
6219 .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() },
6220 .return_type = scalar_ty.toIntern(),
6221 };
6222 const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info);
6223 const init = switch (float_bits) {
60236224 else => unreachable,
6225 16 => try o.f16Const(switch (reduce.operation) {
6226 else => unreachable,
6227 .Min, .Max => std.math.nan(f16),
6228 .Add => -0.0,
6229 .Mul => 1.0,
6230 }),
6231 32 => try o.f32Const(switch (reduce.operation) {
6232 else => unreachable,
6233 .Min, .Max => std.math.nan(f32),
6234 .Add => -0.0,
6235 .Mul => 1.0,
6236 }),
6237 64 => try o.f64Const(switch (reduce.operation) {
6238 else => unreachable,
6239 .Min, .Max => std.math.nan(f64),
6240 .Add => -0.0,
6241 .Mul => 1.0,
6242 }),
6243 80 => try o.f80Const(switch (reduce.operation) {
6244 else => unreachable,
6245 .Min, .Max => std.math.nan(f80),
6246 .Add => -0.0,
6247 .Mul => 1.0,
6248 }),
6249 128 => try o.f128Const(switch (reduce.operation) {
6250 else => unreachable,
6251 .Min, .Max => std.math.nan(f128),
6252 .Add => -0.0,
6253 .Mul => 1.0,
6254 }),
60246255 };
6025 return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(zcu), init_val);
6256 const iterations = operand_ty.vectorLen(zcu);
6257 const is_by_ref = isByRef(operand_ty, zcu);
6258 if (iterations > 1 and is_by_ref) {
6259 const init_ref = try o.lowerConstRef(init, scalar_ty.abiAlignment(zcu).toLlvm());
6260
6261 const entry_block = fg.wip.cursor.block;
6262 const loop_block = try fg.wip.block(2, "reduce.loop");
6263 const done_block = try fg.wip.block(1, "reduce.loop");
6264
6265 _ = try fg.wip.br(loop_block);
6266
6267 fg.wip.cursor = .{ .block = loop_block };
6268 const index = try fg.wip.phi(.i32, "reduce.index");
6269 const result = try fg.wip.phi(.ptr, "reduce.result");
6270
6271 const rhs_elem_ptr = try fg.ptraddScaled(operand, index.toValue(), scalar_ty.abiSize(zcu));
6272 const rhs_elem = try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal);
6273 const next_result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result.toValue(), rhs_elem });
6274
6275 const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "reduce.next_index");
6276 index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip);
6277 result.finish(&.{ init_ref.toValue(), next_result }, &.{ entry_block, loop_block }, &fg.wip);
6278 const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "reduce.is_done");
6279 _ = try fg.wip.brCond(is_done, done_block, loop_block, .none);
6280
6281 fg.wip.cursor = .{ .block = done_block };
6282 return next_result;
6283 }
6284 var result = init.toValue();
6285 for (0..iterations) |index| {
6286 const index_value = try o.builder.intValue(.i32, index);
6287 const rhs_elem = if (is_by_ref) rhs_elem: {
6288 const rhs_elem_ptr = try fg.ptraddConst(operand, index * scalar_ty.abiSize(zcu));
6289 break :rhs_elem try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal);
6290 } else try fg.wip.extractElement(operand, index_value, "reduce.rhs_elem");
6291 result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result, rhs_elem });
6292 }
6293 return result;
60266294}
60276295
6028fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6029 const o = self.object;
6296fn airAggregateInit(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6297 const o = fg.object;
60306298 const zcu = o.zcu;
60316299 const ip = &zcu.intern_pool;
6032 const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
6033 const result_ty = self.typeOfIndex(inst);
6300 const ty_pl = fg.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
6301 const result_ty = fg.typeOfIndex(inst);
60346302 const len: usize = @intCast(result_ty.arrayLen(zcu));
6035 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]);
6303 const elements: []const Air.Inst.Ref = @ptrCast(fg.air.extra.items[ty_pl.payload..][0..len]);
60366304
60376305 switch (result_ty.zigTypeTag(zcu)) {
6038 .vector => {
6039 const llvm_result_ty = try o.lowerType(result_ty, .by_value);
6306 .vector => if (isByRef(result_ty, zcu)) {
6307 const elem_ty = result_ty.childType(zcu);
6308 const elem_size = elem_ty.abiSize(zcu);
6309 const result_ptr = try fg.buildZigAlloca(result_ty, .none);
6310 for (elements, 0..) |elem, elem_index| {
6311 const elem_ptr = try fg.ptraddConst(result_ptr, elem_index * elem_size);
6312 const llvm_elem = try fg.resolveInst(elem);
6313 try fg.store(elem_ptr, .none, llvm_elem, elem_ty, .normal);
6314 }
6315 return result_ptr;
6316 } else {
6317 const llvm_result_ty = try o.lowerType(result_ty, .as_value);
60406318 var vector = try o.builder.poisonValue(llvm_result_ty);
6041 for (elements, 0..) |elem, i| {
6042 const index_u32 = try o.builder.intValue(.i32, i);
6043 const llvm_elem = try self.resolveInst(elem);
6044 vector = try self.wip.insertElement(vector, llvm_elem, index_u32, "");
6319 for (elements, 0..) |elem, elem_index| {
6320 const elem_index_val = try o.builder.intValue(.i32, elem_index);
6321 const llvm_elem = try fg.resolveInst(elem);
6322 vector = try fg.wip.insertElement(vector, llvm_elem, elem_index_val, "");
60456323 }
60466324 return vector;
60476325 },
......@@ -6057,18 +6335,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
60576335 for (elements, struct_type.field_types.get(ip)) |elem, field_ty| {
60586336 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
60596337
6060 const non_int_val = try self.resolveInst(elem);
6338 const non_int_val = try fg.resolveInst(elem);
60616339 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));
60626340 const small_int_ty = try o.builder.intType(ty_bit_size);
60636341 const small_int_val = if (Type.fromInterned(field_ty).isPtrAtRuntime(zcu))
6064 try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "")
6342 try fg.wip.cast(.ptrtoint, non_int_val, small_int_ty, "")
60656343 else
6066 try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");
6344 try fg.wip.cast(.bitcast, non_int_val, small_int_ty, "");
60676345 const shift_rhs = try o.builder.intValue(int_ty, running_bits);
60686346 const extended_int_val =
6069 try self.wip.conv(.unsigned, small_int_val, int_ty, "");
6070 const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, "");
6071 running_int = try self.wip.bin(.@"or", running_int, shifted, "");
6347 try fg.wip.conv(.unsigned, small_int_val, int_ty, "");
6348 const shifted = try fg.wip.bin(.shl, extended_int_val, shift_rhs, "");
6349 running_int = try fg.wip.bin(.@"or", running_int, shifted, "");
60726350 running_bits += ty_bit_size;
60736351 }
60746352 return running_int;
......@@ -6078,19 +6356,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
60786356 // TODO in debug builds init to undef so that the padding will be 0xaa
60796357 // even if we fully populate the fields.
60806358 const struct_align = result_ty.abiAlignment(zcu);
6081 const alloca_inst = try self.buildZigAlloca(result_ty, .none);
6359 const alloca_inst = try fg.buildZigAlloca(result_ty, .none);
60826360
60836361 for (elements, 0..) |elem, field_index| {
60846362 if (result_ty.structFieldIsComptime(field_index, zcu)) continue;
60856363 const field_ty = result_ty.fieldType(field_index, zcu);
60866364 if (!field_ty.hasRuntimeBits(zcu)) continue;
60876365 const offset = result_ty.structFieldOffset(field_index, zcu);
6088 const field_ptr = try self.ptraddConst(alloca_inst, offset);
6366 const field_ptr = try fg.ptraddConst(alloca_inst, offset);
60896367 const field_ptr_align = struct_align.offset(offset);
60906368
6091 const llvm_field_val = try self.resolveInst(elem);
6369 const llvm_field_val = try fg.resolveInst(elem);
60926370
6093 try self.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal);
6371 try fg.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal);
60946372 }
60956373
60966374 return alloca_inst;
......@@ -6099,21 +6377,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
60996377 .array => {
61006378 assert(isByRef(result_ty, zcu));
61016379
6102 const alloca_inst = try self.buildZigAlloca(result_ty, .none);
6380 const alloca_inst = try fg.buildZigAlloca(result_ty, .none);
61036381
61046382 const array_info = result_ty.arrayInfo(zcu);
61056383
61066384 const elem_size = array_info.elem_type.abiSize(zcu);
61076385
61086386 for (elements, 0..) |elem, i| {
6109 const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i);
6110 const llvm_elem = try self.resolveInst(elem);
6111 try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);
6387 const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * i);
6388 const llvm_elem = try fg.resolveInst(elem);
6389 try fg.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);
61126390 }
61136391 if (array_info.sentinel) |sent_val| {
6114 const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len);
6115 const llvm_elem = try self.resolveValue(sent_val);
6116 try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);
6392 const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * array_info.len);
6393 const llvm_elem = try fg.resolveValue(sent_val);
6394 try fg.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);
61176395 }
61186396
61196397 return alloca_inst;
......@@ -6153,10 +6431,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
61536431 const loaded_enum = ip.loadEnumType(tag_ty.toIntern());
61546432 const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) {
61556433 .none => try o.builder.intConst(
6156 try o.lowerType(.fromInterned(union_obj.enum_tag_type), .by_value),
6434 try o.lowerType(.fromInterned(union_obj.enum_tag_type), .as_value),
61576435 extra.field_index, // auto-numbered
61586436 ),
6159 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value),
6437 else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value),
61606438 };
61616439 const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset());
61626440 try self.store(tag_ptr, layout.tag_align, llvm_tag_val.toValue(), tag_ty, .normal);
......@@ -6218,7 +6496,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
62186496 const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op;
62196497 const inst_ty = self.typeOfIndex(inst);
62206498 const operand = try self.resolveInst(ty_op.operand);
6221 return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .by_value), "");
6499 return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .as_value), "");
62226500}
62236501
62246502fn workIntrinsic(
......@@ -6370,7 +6648,7 @@ fn load(
63706648 };
63716649
63726650 if (isByRef(load_ty, zcu)) {
6373 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
6651 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
63746652 const result_ptr = try fg.buildZigAlloca(load_ty, .none);
63756653 _ = try fg.wip.callMemCpy(
63766654 result_ptr,
......@@ -6384,10 +6662,10 @@ fn load(
63846662 return result_ptr;
63856663 }
63866664
6387 const llvm_memory_ty = try o.lowerType(load_ty, .in_memory);
6388 const llvm_value_ty = try o.lowerType(load_ty, .by_value);
6665 const llvm_access_ty = try o.lowerType(load_ty, .memory_access);
6666 const llvm_value_ty = try o.lowerType(load_ty, .as_value);
63896667
6390 if (llvm_memory_ty != llvm_value_ty) {
6668 if (llvm_access_ty != llvm_value_ty) {
63916669 assert(load_ty.isAbiInt(zcu));
63926670 // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special
63936671 // handling for these, as LLVM's documented semantics are a valid implementation of Zig's
......@@ -6401,7 +6679,7 @@ fn load(
64016679 //
64026680 // Therefore, we handle these memory accesses specially: in this case we will actually load
64036681 // the next-largest "natural" integer type and then truncate to `load_ty`.
6404 const loaded = try fg.wip.load(access_kind, llvm_memory_ty, ptr, llvm_ptr_align, "");
6682 const loaded = try fg.wip.load(access_kind, llvm_access_ty, ptr, llvm_ptr_align, "");
64056683 // For packed structs, current Zig semantics don't really allow us to make the padding bits
64066684 // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is
64076685 // implemented, but until then, do a normal trunc for packed types.
......@@ -6443,7 +6721,7 @@ fn store(
64436721 };
64446722
64456723 if (isByRef(elem_ty, zcu)) {
6446 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
6724 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
64476725 _ = try fg.wip.callMemCpy(
64486726 ptr,
64496727 llvm_ptr_align,
......@@ -6456,45 +6734,31 @@ fn store(
64566734 return;
64576735 }
64586736
6459 assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .by_value));
6737 assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .as_value));
64606738
6461 const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory);
6462 const llvm_value_ty = try o.lowerType(elem_ty, .by_value);
6739 const llvm_access_ty = try o.lowerType(elem_ty, .memory_access);
6740 const llvm_value_ty = try o.lowerType(elem_ty, .as_value);
64636741
6464 if (llvm_memory_ty != llvm_value_ty) {
6742 if (llvm_access_ty != llvm_value_ty) {
64656743 assert(elem_ty.isAbiInt(zcu));
64666744 // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see
64676745 // the corresponding comment in `FuncGen.load` for more details.
64686746 const extended = try fg.wip.cast(switch (elem_ty.intInfo(zcu).signedness) {
64696747 .unsigned => .zext,
64706748 .signed => .sext,
6471 }, elem, llvm_memory_ty, "");
6472 _ = try fg.wip.storeAtomic(
6473 access_kind,
6474 extended,
6475 ptr,
6476 fg.sync_scope,
6477 .none,
6478 llvm_ptr_align,
6479 );
6749 }, elem, llvm_access_ty, "");
6750 _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align);
64806751 return;
64816752 }
64826753
64836754 // `elem_ty` is a simple by-val type which requires no special handling.
6484 _ = try fg.wip.storeAtomic(
6485 access_kind,
6486 elem,
6487 ptr,
6488 fg.sync_scope,
6489 .none,
6490 llvm_ptr_align,
6491 );
6755 _ = try fg.wip.store(access_kind, elem, ptr, llvm_ptr_align);
64926756}
64936757
64946758fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {
64956759 const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
64966760 const o = fg.object;
6497 const usize_ty = try o.lowerType(.usize, .by_value);
6761 const usize_ty = try o.lowerType(.usize, .as_value);
64986762 const zero = try o.builder.intValue(usize_ty, 0);
64996763 const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED);
65006764 const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, "");
......@@ -6516,7 +6780,7 @@ fn valgrindClientRequest(
65166780 const target = zcu.getTarget();
65176781 if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value;
65186782
6519 const llvm_usize = try o.lowerType(.usize, .by_value);
6783 const llvm_usize = try o.lowerType(.usize, .as_value);
65206784 const usize_align = Type.usize.abiAlignment(zcu).toLlvm();
65216785
65226786 const array_llvm_ty = try o.builder.arrayType(6, llvm_usize);
......@@ -6650,13 +6914,14 @@ fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type {
66506914
66516915const ParamTypeIterator = struct {
66526916 object: *Object,
6653 fn_info: InternPool.Key.FuncType,
6917 cc: std.lang.CallingConvention,
6918 param_types: []const InternPool.Index,
66546919 zig_index: u32,
66556920 llvm_index: u32,
66566921 types_len: u32,
66576922 types_buffer: [8]Builder.Type,
66586923 offsets_buffer: [9]u64,
6659 byval_attr: bool,
6924 byval_attr: ?Object.Byval,
66606925
66616926 const Lowering = union(enum) {
66626927 no_bits,
......@@ -6672,88 +6937,78 @@ const ParamTypeIterator = struct {
66726937 };
66736938
66746939 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
6675 if (it.zig_index >= it.fn_info.param_types.len) return null;
6676 const ip = &it.object.zcu.intern_pool;
6677 const ty = it.fn_info.param_types.get(ip)[it.zig_index];
6678 it.byval_attr = false;
6940 if (it.zig_index >= it.param_types.len) return null;
6941 const ty = it.param_types[it.zig_index];
6942 it.byval_attr = null;
66796943 return nextInner(it, Type.fromInterned(ty));
66806944 }
66816945
66826946 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
6683 fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering {
6684 const ip = &it.object.zcu.intern_pool;
6685 if (it.zig_index >= it.fn_info.param_types.len) {
6686 if (it.zig_index >= args.len) {
6947 fn nextCall(it: *ParamTypeIterator, arg_types: []const InternPool.Index) Allocator.Error!?Lowering {
6948 if (it.zig_index >= it.param_types.len) {
6949 if (it.zig_index >= arg_types.len) {
66876950 return null;
66886951 } else {
6689 return nextInner(it, fg.typeOf(args[it.zig_index]));
6952 return nextInner(it, .fromInterned(arg_types[it.zig_index]));
66906953 }
66916954 } else {
6692 return nextInner(it, Type.fromInterned(it.fn_info.param_types.get(ip)[it.zig_index]));
6955 return nextInner(it, .fromInterned(it.param_types[it.zig_index]));
66936956 }
66946957 }
66956958
66966959 fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
66976960 const zcu = it.object.zcu;
6698 const target = zcu.getTarget();
6699
6961 ty.assertHasLayout(zcu);
67006962 if (!ty.hasRuntimeBits(zcu)) {
67016963 it.zig_index += 1;
67026964 return .no_bits;
67036965 }
6704 switch (it.fn_info.cc) {
6966 switch (it.cc) {
67056967 .@"inline" => unreachable,
67066968 .auto => {
67076969 it.zig_index += 1;
67086970 it.llvm_index += 1;
6971
6972 // Match the c calling convention in some cases to avoid llvm bugs.
6973 const target = zcu.getTarget();
6974 if (target.cpu.arch == .x86_64 and ty.isVector(zcu) and ty.childType(zcu).toIntern() == .bool_type) return switch (ty.vectorLen(zcu)) {
6975 0 => .no_bits,
6976 1...32 => .abi_sized_int,
6977 33...64 => {
6978 it.types_buffer[0..1].* = .{.double};
6979 it.offsets_buffer[0..2].* = .{ 0, 8 };
6980 it.types_len = 1;
6981 return .multiple_llvm_types;
6982 },
6983 else => .byval,
6984 };
6985
67096986 if (ty.isSlice(zcu) or
67106987 (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu)))
67116988 {
67126989 it.llvm_index += 1;
67136990 return .slice;
6714 } else if (isByRef(ty, zcu)) {
6715 return .byref;
6716 } else if (target.cpu.arch.isX86() and
6717 !target.cpu.has(.x86, .avx512f) and
6718 ty.totalVectorBits(zcu) >= 512)
6719 {
6720 // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns
6721 // "512-bit vector arguments require 'avx512f' for AVX512"
6722 return .byref;
6723 } else {
6724 return .byval;
67256991 }
6992 if (isByRef(ty, zcu)) return .byref;
6993 return .byval;
67266994 },
67276995 .async => {
67286996 @panic("TODO implement async function lowering in the LLVM backend");
67296997 },
6730 .x86_64_sysv, .x86_64_x32 => return it.nextSystemV(ty),
6731 .x86_64_win => return it.nextWin64(ty),
6732 .x86_stdcall => {
6733 it.zig_index += 1;
6734 it.llvm_index += 1;
6735
6736 if (isScalar(zcu, ty)) {
6737 return .byval;
6738 } else {
6739 it.byval_attr = true;
6740 return .byref;
6741 }
6742 },
67436998 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {
67446999 it.zig_index += 1;
67457000 it.llvm_index += 1;
67467001 switch (aarch64_c_abi.classifyType(ty, zcu)) {
67477002 .memory => return .byref_mut,
6748 .float_array => |len| return Lowering{ .float_array = len },
7003 .float_array => |len| return .{ .float_array = len },
67497004 .byval => return .byval,
67507005 .integer => {
6751 it.types_len = 1;
67527006 it.types_buffer[0..1].* = .{.i64};
67537007 it.offsets_buffer[0..2].* = .{ 0, 8 };
7008 it.types_len = 1;
67547009 return .multiple_llvm_types;
67557010 },
6756 .double_integer => return Lowering{ .i64_array = 2 },
7011 .double_integer => return .{ .i64_array = 2 },
67577012 }
67587013 },
67597014 .arm_aapcs, .arm_aapcs_vfp => {
......@@ -6761,26 +7016,101 @@ const ParamTypeIterator = struct {
67617016 it.llvm_index += 1;
67627017 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {
67637018 .memory => {
6764 it.byval_attr = true;
7019 it.byval_attr = .{};
67657020 return .byref;
67667021 },
67677022 .byval => return .byval,
6768 .i32_array => |size| return Lowering{ .i32_array = size },
6769 .i64_array => |size| return Lowering{ .i64_array = size },
7023 .i32_array => |size| return .{ .i32_array = size },
7024 .i64_array => |size| return .{ .i64_array = size },
67707025 }
67717026 },
7027 .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ty, zcu)) {
7028 .ignored => {
7029 it.zig_index += 1;
7030 return .no_bits;
7031 },
7032 .gar, .far => {
7033 it.zig_index += 1;
7034 it.llvm_index += 1;
7035 return .byval;
7036 },
7037 .member => |member_ty| {
7038 it.types_buffer[0..1].* = .{
7039 try it.object.lowerType(member_ty, .as_value),
7040 };
7041 it.offsets_buffer[0..2].* = .{ 0, member_ty.abiSize(zcu) };
7042 it.types_len = 1;
7043 it.zig_index += 1;
7044 it.llvm_index += 1;
7045 return .multiple_llvm_types;
7046 },
7047 .member_pair => |member_tys| {
7048 it.types_buffer[0..2].* = .{
7049 try it.object.lowerType(member_tys[0], .as_value),
7050 try it.object.lowerType(member_tys[1], .as_value),
7051 };
7052 const first_size = member_tys[0].abiSize(zcu);
7053 const second_size = member_tys[0].abiSize(zcu);
7054 it.offsets_buffer[0..3].* = .{ 0, first_size, first_size + second_size };
7055 it.types_len = 2;
7056 it.zig_index += 1;
7057 it.llvm_index += 2;
7058 return .multiple_llvm_types;
7059 },
7060 .memory_gar => {
7061 switch (it.cc) {
7062 else => unreachable,
7063 .loongarch32_ilp32 => {
7064 it.types_buffer[0..1].* = .{.i32};
7065 it.offsets_buffer[0..2].* = .{ 0, 4 };
7066 },
7067 .loongarch64_lp64 => {
7068 it.types_buffer[0..1].* = .{.i64};
7069 it.offsets_buffer[0..2].* = .{ 0, 8 };
7070 },
7071 }
7072 it.types_len = 1;
7073 it.zig_index += 1;
7074 it.llvm_index += 1;
7075 return .multiple_llvm_types;
7076 },
7077 .memory_gar_pair => {
7078 it.zig_index += 1;
7079 it.llvm_index += 1;
7080 return switch (it.cc) {
7081 else => unreachable,
7082 .loongarch32_ilp32 => .{ .i32_array = 2 },
7083 .loongarch64_lp64 => .{ .i64_array = 2 },
7084 };
7085 },
7086 .address => {
7087 it.zig_index += 1;
7088 it.llvm_index += 1;
7089 return .byref;
7090 },
7091 },
67727092 .mips_o32 => {
67737093 it.zig_index += 1;
67747094 it.llvm_index += 1;
67757095 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {
67767096 .memory => {
6777 it.byval_attr = true;
7097 it.byval_attr = .{};
67787098 return .byref;
67797099 },
67807100 .byval => return .byval,
6781 .i32_array => |size| return Lowering{ .i32_array = size },
7101 .i32_array => |size| return .{ .i32_array = size },
67827102 }
67837103 },
7104 .powerpc64_elf_v2 => {
7105 it.zig_index += 1;
7106 it.llvm_index += 1;
7107 if (isByRef(ty, zcu)) return switch (ty.abiSize(zcu)) {
7108 1...8 => .abi_sized_int,
7109 9...64 => |abi_size| .{ .i64_array = @intCast(@divCeil(abi_size, 8)) },
7110 else => .byref,
7111 };
7112 return .byval; // TODO
7113 },
67847114 .riscv64_lp64, .riscv32_ilp32 => {
67857115 it.zig_index += 1;
67867116 it.llvm_index += 1;
......@@ -6788,7 +7118,7 @@ const ParamTypeIterator = struct {
67887118 .memory => return .byref_mut,
67897119 .byval => return .byval,
67907120 .integer => return .abi_sized_int,
6791 .double_integer => return Lowering{ .i64_array = 2 },
7121 .double_integer => return .{ .i64_array = 2 },
67927122 .fields => {
67937123 it.types_len = 0;
67947124 var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct|
......@@ -6798,7 +7128,7 @@ const ParamTypeIterator = struct {
67987128 while (field_it.next()) |field_index| {
67997129 const field_ty = ty.fieldType(field_index, zcu);
68007130 if (!field_ty.hasRuntimeBits(zcu)) continue;
6801 it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .by_value);
7131 it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .as_value);
68027132 it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu);
68037133 it.types_len += 1;
68047134 }
......@@ -6808,6 +7138,24 @@ const ParamTypeIterator = struct {
68087138 },
68097139 }
68107140 },
7141 .s390x_sysv, .s390x_sysv_vx => {
7142 it.zig_index += 1;
7143 switch (s390x_c_abi.classifyType(ty, .arg, zcu)) {
7144 .none => return .no_bits,
7145 .double_or_float, .vector, .simple => {
7146 it.llvm_index += 1;
7147 return .byval;
7148 },
7149 .simple_aggregate => {
7150 it.llvm_index += 1;
7151 return .abi_sized_int;
7152 },
7153 .pointer => {
7154 it.llvm_index += 1;
7155 return .byref_mut;
7156 },
7157 }
7158 },
68117159 .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) {
68127160 .direct => |scalar_ty| {
68137161 if (isScalar(zcu, ty)) {
......@@ -6815,21 +7163,80 @@ const ParamTypeIterator = struct {
68157163 it.llvm_index += 1;
68167164 return .byval;
68177165 } else {
6818 it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .by_value)};
7166 it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)};
68197167 it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };
68207168 it.types_len = 1;
6821 it.llvm_index += 1;
68227169 it.zig_index += 1;
7170 it.llvm_index += 1;
68237171 return .multiple_llvm_types;
68247172 }
68257173 },
68267174 .indirect => {
68277175 it.zig_index += 1;
68287176 it.llvm_index += 1;
6829 it.byval_attr = true;
7177 it.byval_attr = .{};
68307178 return .byref;
68317179 },
68327180 },
7181 .x86_stdcall => {
7182 it.zig_index += 1;
7183 it.llvm_index += 1;
7184
7185 if (isScalar(zcu, ty)) {
7186 return .byval;
7187 } else {
7188 it.byval_attr = .{};
7189 return .byref;
7190 }
7191 },
7192 .x86_sysv, .x86_win, .x86_mingw => {
7193 if (isByRef(ty, zcu)) {
7194 var items_buf: [1]codegen.FlattenedItem = undefined;
7195 if (codegen.flattenType(&items_buf, ty, zcu, .{
7196 .allow_arrays = false,
7197 })) |items| one_float: {
7198 if (items.len != 1 or items[0].offset != 0) break :one_float;
7199 const item_ty = items[0].type orelse break :one_float;
7200 if (!item_ty.isRuntimeFloat()) break :one_float;
7201 it.types_buffer[0..1].*, it.offsets_buffer[0..2].* =
7202 switch (item_ty.floatBits(zcu.getTarget())) {
7203 else => unreachable,
7204 32 => .{ .{.float}, .{ 0, 4 } },
7205 64 => .{ .{.double}, .{ 0, 8 } },
7206 16, 80, 128 => break :one_float,
7207 };
7208 it.types_len = 1;
7209 it.zig_index += 1;
7210 it.llvm_index += 1;
7211 return .multiple_llvm_types;
7212 }
7213 it.zig_index += 1;
7214 it.llvm_index += 1;
7215 it.byval_attr = .{ .alignment = .@"4" };
7216 return .byref;
7217 }
7218 if (ty.isAbiInt(zcu)) switch (ty.intInfo(zcu).bits) {
7219 else => unreachable,
7220 8, 16, 32, 64 => {
7221 it.zig_index += 1;
7222 it.llvm_index += 1;
7223 return .byval;
7224 },
7225 128 => {
7226 it.types_buffer[0..2].* = .{ .i64, .i64 };
7227 it.offsets_buffer[0..3].* = .{ 0, 8, 16 };
7228 it.types_len = 2;
7229 it.zig_index += 1;
7230 it.llvm_index += 2;
7231 return .multiple_llvm_types;
7232 },
7233 };
7234 it.zig_index += 1;
7235 it.llvm_index += 1;
7236 return .byval;
7237 },
7238 .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty),
7239 .x86_64_win => return it.next_x86_64_win(ty),
68337240 // TODO investigate other callconvs
68347241 else => {
68357242 it.zig_index += 1;
......@@ -6839,7 +7246,7 @@ const ParamTypeIterator = struct {
68397246 }
68407247 }
68417248
6842 fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
7249 fn next_x86_64_win(it: *ParamTypeIterator, ty: Type) Lowering {
68437250 const zcu = it.object.zcu;
68447251 switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) {
68457252 .integer => {
......@@ -6880,119 +7287,114 @@ const ParamTypeIterator = struct {
68807287 }
68817288 }
68827289
6883 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
6884 const zcu = it.object.zcu;
6885 const ip = &zcu.intern_pool;
6886 ty.assertHasLayout(zcu);
6887 const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg);
6888 if (classes[0] == .memory) {
6889 it.zig_index += 1;
6890 it.llvm_index += 1;
6891 it.byval_attr = true;
6892 return .byref;
6893 }
6894 if (isScalar(zcu, ty)) {
6895 it.zig_index += 1;
6896 it.llvm_index += 1;
6897 return .byval;
6898 }
6899 var types_index: u32 = 0;
6900 var offset: u64 = 0;
6901 for (classes) |class| {
6902 switch (class) {
6903 .integer => {
6904 it.types_buffer[types_index] = .i64;
6905 it.offsets_buffer[types_index] = offset;
6906 types_index += 1;
6907 },
6908 .sse => {
6909 it.types_buffer[types_index] = .double;
6910 it.offsets_buffer[types_index] = offset;
6911 types_index += 1;
6912 },
6913 .sseup => {
6914 if (it.types_buffer[types_index - 1] == .double) {
6915 it.types_buffer[types_index - 1] = .fp128;
6916 } else {
6917 it.types_buffer[types_index] = .double;
6918 it.offsets_buffer[types_index] = offset;
6919 types_index += 1;
7290 fn next_x86_64_sysv(it: *ParamTypeIterator, ty: Type) Allocator.Error!Lowering {
7291 const o = it.object;
7292 const zcu = o.zcu;
7293 const target = zcu.getTarget();
7294 const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg);
7295 var types_len: u32 = 0;
7296 const classes_len = for (classes, 0..) |class, class_index| switch (class) {
7297 .integer => {
7298 it.types_buffer[types_len] = try o.builder.intType(@min(8 * ty.abiSize(zcu) - 64 * class_index, 64));
7299 it.offsets_buffer[types_len] = 8 * class_index;
7300 types_len += 1;
7301 },
7302 .sse => {
7303 it.types_buffer[types_len] = .double;
7304 it.offsets_buffer[types_len] = 8 * class_index;
7305 types_len += 1;
7306 },
7307 .sseup => {
7308 if (it.types_buffer[types_len - 1] == .double) {
7309 if (ty.isVector(zcu)) {
7310 it.zig_index += 1;
7311 it.llvm_index += 1;
7312 return .byval;
69207313 }
6921 },
6922 .float => {
6923 it.types_buffer[types_index] = .float;
6924 it.offsets_buffer[types_index] = offset;
6925 types_index += 1;
6926 },
6927 .float_combine => {
6928 it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float);
6929 it.offsets_buffer[types_index] = offset;
6930 types_index += 1;
6931 },
6932 .x87 => {
6933 it.zig_index += 1;
6934 it.llvm_index += 1;
6935 it.byval_attr = true;
6936 return .byref;
6937 },
6938 .x87up => unreachable,
6939 .none => break,
6940 .memory => unreachable, // handled above
6941 .win_i128 => unreachable, // windows only
6942 .bool_vector_mask,
6943 .integer_per_element,
6944 .sse_per_element,
6945 .sse_sse_x87_per_qword,
6946 .sse_per_xword,
6947 .sse_per_yword,
6948 .sse_per_zword,
6949 => unreachable, // vectors already handled by `isScalar` above
6950 }
6951 offset += 8;
6952 }
6953 const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer});
6954 if (first_non_integer == null or classes[first_non_integer.?] == .none) {
6955 assert(first_non_integer orelse classes.len == types_index);
6956 if (types_index == 1) {
7314 it.types_buffer[types_len - 1] = .fp128;
7315 } else {
7316 it.types_buffer[types_len] = .double;
7317 it.offsets_buffer[types_len] = 8 * class_index;
7318 types_len += 1;
7319 }
7320 },
7321 .float => {
7322 it.types_buffer[types_len] = .float;
7323 it.offsets_buffer[types_len] = 8 * class_index;
7324 types_len += 1;
7325 },
7326 .float_combine => {
7327 it.types_buffer[types_len] = try it.object.builder.vectorType(.normal, 2, .float);
7328 it.offsets_buffer[types_len] = 8 * class_index;
7329 types_len += 1;
7330 },
7331 .x87 => {
69577332 it.zig_index += 1;
69587333 it.llvm_index += 1;
6959 return .abi_sized_int;
6960 }
6961 if (it.llvm_index + types_index > 6) {
7334 it.byval_attr = .{};
7335 return .byref;
7336 },
7337 .x87up => unreachable,
7338 .none => break class_index,
7339 .memory => {
7340 it.zig_index += 1;
7341 it.llvm_index += 1;
7342 it.byval_attr = .{};
7343 return .byref;
7344 },
7345 .win_i128 => unreachable, // windows only
7346 .bool_vector_mask,
7347 .integer_per_element,
7348 .sse_per_element,
7349 .sse_sse_x87_per_qword,
7350 .sse_per_xword,
7351 .sse_per_yword,
7352 .sse_per_zword,
7353 => {
7354 it.zig_index += 1;
7355 it.llvm_index += 1;
7356 return .byval;
7357 },
7358 } else classes.len;
7359 if (types_len > 1) {
7360 if (it.llvm_index + classes_len > 6) {
69627361 it.zig_index += 1;
69637362 it.llvm_index += 1;
6964 it.byval_attr = true;
7363 it.byval_attr = .{};
69657364 return .byref;
69667365 }
6967 switch (ip.indexToKey(ty.toIntern())) {
6968 .struct_type => {
6969 const size = ty.abiSize(zcu);
6970 assert(@divCeil(size, 8) == types_index);
6971 if (size % 8 > 0) {
6972 it.types_buffer[types_index - 1] =
6973 try it.object.builder.intType(@intCast(size % 8 * 8));
6974 }
6975 },
6976 else => {},
7366 } else if (!isByRef(ty, zcu)) {
7367 const llvm_ty = try o.lowerType(ty, .as_value);
7368 if (it.types_buffer[0] == llvm_ty or
7369 (it.types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)))
7370 {
7371 it.zig_index += 1;
7372 it.llvm_index += 1;
7373 return .byval;
69777374 }
69787375 }
6979 it.offsets_buffer[types_index] = offset;
6980 it.types_len = types_index;
6981 it.llvm_index += types_index;
7376 it.offsets_buffer[types_len] = 8 * classes_len;
7377 it.types_len = types_len;
7378 it.llvm_index += types_len;
69827379 it.zig_index += 1;
69837380 return .multiple_llvm_types;
69847381 }
69857382};
6986pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator {
7383pub fn iterateParamTypes(
7384 object: *Object,
7385 cc: std.lang.CallingConvention,
7386 param_types: []const InternPool.Index,
7387) ParamTypeIterator {
69877388 return .{
69887389 .object = object,
6989 .fn_info = fn_info,
7390 .cc = cc,
7391 .param_types = param_types,
69907392 .zig_index = 0,
69917393 .llvm_index = 0,
69927394 .types_len = undefined,
69937395 .types_buffer = undefined,
69947396 .offsets_buffer = undefined,
6995 .byval_attr = false,
7397 .byval_attr = null,
69967398 };
69977399}
69987400
......@@ -7017,54 +7419,68 @@ pub const FnReturnStrat = union(enum) {
70177419/// In order to support the C calling convention, some return types need to be lowered
70187420/// completely differently in the function prototype to honor the C ABI, and then
70197421/// be effectively bitcasted to the actual return type.
7020pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
7422pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) Allocator.Error!FnReturnStrat {
70217423 const zcu = o.zcu;
7022 const ret_ty: Type = .fromInterned(fn_info.return_type);
70237424 ret_ty.assertHasLayout(zcu);
70247425 if (!ret_ty.hasRuntimeBits(zcu)) return .void;
7025 switch (fn_info.cc) {
7426 return switch (cc) {
70267427 .@"inline" => unreachable,
70277428 .auto => {
7028 if (isByRef(ret_ty, zcu)) return .sret;
7029
7429 // Match the c calling convention in some cases to avoid llvm bugs.
70307430 const target = zcu.getTarget();
7031 if (target.cpu.arch.isX86() and
7032 !target.cpu.has(.x86, .avx512f) and
7033 ret_ty.totalVectorBits(zcu) >= 512)
7034 {
7035 // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns
7036 // "512-bit vector arguments require 'avx512f' for AVX512"
7037 return .sret;
7038 }
7039
7040 return .by_val;
7431 if (target.cpu.arch == .x86_64 and ret_ty.isVector(zcu) and ret_ty.childType(zcu).toIntern() == .bool_type) return switch (ret_ty.vectorLen(zcu)) {
7432 0 => .void,
7433 1...8 => .{ .mem_cast = .i8 },
7434 9...16 => .{ .mem_cast = .i16 },
7435 17...32 => .{ .mem_cast = .i32 },
7436 33...64 => .{ .mem_cast = .double },
7437 else => .by_val,
7438 };
7439 return if (isByRef(ret_ty, zcu)) .sret else .by_val;
70417440 },
7042 .x86_64_sysv, .x86_64_x32 => return lowerSystemVFnRetTy(o, fn_info),
7043 .x86_64_win => return lowerWin64FnRetTy(o, fn_info),
7044 .x86_stdcall => if (isScalar(zcu, ret_ty)) {
7045 assert(!isByRef(ret_ty, zcu));
7046 return .by_val;
7047 } else return .sret,
7048 .x86_fastcall => return lowerX86FastcallFnRetTy(o, zcu, ret_ty),
7049 .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val,
70507441 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) {
7051 .memory => return .sret,
7052 .float_array, .byval => return .forceByVal(o, ret_ty),
7053 .integer => return .{ .mem_cast = .i64 },
7054 .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) },
7442 .memory => .sret,
7443 .float_array, .byval => .forceByVal(o, ret_ty),
7444 .integer => .{ .mem_cast = .i64 },
7445 .double_integer => .{ .mem_cast = try o.builder.arrayType(2, .i64) },
70557446 },
70567447 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) {
7057 .memory, .i64_array => return .sret,
7058 .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret,
7059 .byval => return .forceByVal(o, ret_ty),
7448 .memory, .i64_array => .sret,
7449 .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret,
7450 .byval => .forceByVal(o, ret_ty),
7451 },
7452 .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ret_ty, zcu)) {
7453 .ignored => .void,
7454 .gar, .far => .by_val,
7455 .member => |member_ty| .{ .mem_cast = try o.lowerType(member_ty, .as_value) },
7456 .member_pair => |member_tys| .{ .mem_cast = try o.builder.structType(.normal, &.{
7457 try o.lowerType(member_tys[0], .as_value),
7458 try o.lowerType(member_tys[1], .as_value),
7459 }) },
7460 .memory_gar => .{ .mem_cast = switch (cc) {
7461 else => unreachable,
7462 .loongarch32_ilp32 => .i32,
7463 .loongarch64_lp64 => .i64,
7464 } },
7465 .memory_gar_pair => .{ .mem_cast = try o.builder.arrayType(2, switch (cc) {
7466 else => unreachable,
7467 .loongarch32_ilp32 => .i32,
7468 .loongarch64_lp64 => .i64,
7469 }) },
7470 .address => .sret,
70607471 },
70617472 .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) {
7062 .memory, .i32_array => return .sret,
7063 .byval => return .forceByVal(o, ret_ty),
7473 .memory, .i32_array => .sret,
7474 .byval => .forceByVal(o, ret_ty),
70647475 },
7476 .powerpc64_elf_v2 => if (isByRef(ret_ty, zcu)) switch (ret_ty.abiSize(zcu)) {
7477 1...8 => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
7478 9...16 => .{ .mem_cast = try o.builder.structType(.normal, &.{ .i64, .i64 }) },
7479 else => .sret,
7480 } else .by_val, // TODO
70657481 .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) {
7066 .memory => return .sret,
7067 .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
7482 .memory => .sret,
7483 .integer => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
70687484 .double_integer => {
70697485 const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) {
70707486 .riscv64, .riscv64be => .i64,
......@@ -7073,34 +7489,78 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err
70737489 };
70747490 return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) };
70757491 },
7076 .byval => return .forceByVal(o, ret_ty),
7492 .byval => .forceByVal(o, ret_ty),
70777493 .fields => {
70787494 var types_len: usize = 0;
70797495 var types: [8]Builder.Type = undefined;
70807496 for (0..ret_ty.structFieldCount(zcu)) |field_index| {
70817497 const field_ty = ret_ty.fieldType(field_index, zcu);
70827498 if (!field_ty.hasRuntimeBits(zcu)) continue;
7083 types[types_len] = try o.lowerType(field_ty, .by_value);
7499 types[types_len] = try o.lowerType(field_ty, .as_value);
70847500 types_len += 1;
70857501 }
70867502 return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) };
70877503 },
70887504 },
7505 .s390x_sysv, .s390x_sysv_vx => switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) {
7506 .none => .void,
7507 .double_or_float, .vector, .simple => .by_val,
7508 .simple_aggregate => unreachable,
7509 .pointer => .sret,
7510 },
70897511 .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) {
70907512 .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {
70917513 assert(!isByRef(ret_ty, zcu));
70927514 return .by_val;
7093 } else {
7094 return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) };
7095 },
7096 .indirect => return .sret,
7515 } else .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) },
7516 .indirect => .sret,
70977517 },
7518 .x86_stdcall => if (isScalar(zcu, ret_ty)) {
7519 assert(!isByRef(ret_ty, zcu));
7520 return .by_val;
7521 } else .sret,
7522 .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty),
7523 .x86_sysv, .x86_win, .x86_mingw => if (isByRef(ret_ty, zcu)) {
7524 switch (cc) {
7525 else => unreachable,
7526 .x86_sysv => return .sret,
7527 .x86_win => {},
7528 .x86_mingw => {
7529 var items_buf: [1]codegen.FlattenedItem = undefined;
7530 if (codegen.flattenType(&items_buf, ret_ty, zcu, .{})) |items| one_float: {
7531 if (items.len != 1 or items[0].offset != 0) break :one_float;
7532 const item_ty = items[0].type orelse break :one_float;
7533 if (!item_ty.isRuntimeFloat()) break :one_float;
7534 return .{ .mem_cast = switch (item_ty.floatBits(zcu.getTarget())) {
7535 else => unreachable,
7536 16 => .half,
7537 32 => .float,
7538 64 => .double,
7539 80, 128 => break :one_float,
7540 } };
7541 }
7542 },
7543 }
7544 return switch (ret_ty.abiSize(zcu)) {
7545 0 => .void,
7546 1 => .{ .mem_cast = .i8 },
7547 2 => .{ .mem_cast = .i16 },
7548 4 => .{ .mem_cast = .i32 },
7549 8 => .{ .mem_cast = .i64 },
7550 else => .sret,
7551 };
7552 } else if (ret_ty.isAbiInt(zcu) and ret_ty.intInfo(zcu).bits > 64)
7553 .sret
7554 else
7555 .by_val,
7556 .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty),
7557 .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty),
70987558 // TODO investigate other callconvs
7099 else => return .forceByVal(o, ret_ty),
7100 }
7559 else => .forceByVal(o, ret_ty),
7560 };
71017561}
71027562
7103fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat {
7563fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat {
71047564 if (isScalar(zcu, ty)) {
71057565 assert(!isByRef(ty, zcu));
71067566 return .by_val;
......@@ -7115,9 +7575,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe
71157575 return .sret;
71167576}
71177577
7118fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
7578fn fnReturnStrat_x86_64_win(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat {
71197579 const zcu = o.zcu;
7120 const ret_ty = Type.fromInterned(fn_info.return_type);
71217580 switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) {
71227581 .integer => if (isScalar(zcu, ret_ty)) {
71237582 assert(!isByRef(ret_ty, zcu));
......@@ -7150,78 +7609,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err
71507609 }
71517610}
71527611
7153fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
7612fn fnReturnStrat_x86_64_sysv(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat {
71547613 const zcu = o.zcu;
7155 const ip = &zcu.intern_pool;
7156 const ret_ty = Type.fromInterned(fn_info.return_type);
7157 if (isScalar(zcu, ret_ty)) {
7158 assert(!isByRef(ret_ty, zcu));
7159 return .by_val;
7160 }
71617614 const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret);
7162 var types_index: u32 = 0;
71637615 var types_buffer: [8]Builder.Type = undefined;
7164 for (classes) |class| {
7165 switch (class) {
7166 .integer => {
7167 types_buffer[types_index] = .i64;
7168 types_index += 1;
7169 },
7170 .sse => {
7171 types_buffer[types_index] = .double;
7172 types_index += 1;
7173 },
7174 .sseup => {
7175 if (types_buffer[types_index - 1] == .double) {
7176 types_buffer[types_index - 1] = .fp128;
7177 } else {
7178 types_buffer[types_index] = .double;
7179 types_index += 1;
7180 }
7181 },
7182 .float => {
7183 types_buffer[types_index] = .float;
7184 types_index += 1;
7185 },
7186 .float_combine => {
7187 types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float);
7188 types_index += 1;
7189 },
7190 .x87 => {
7191 if (types_index != 0 or classes[2] != .none) return .sret;
7192 types_buffer[types_index] = .x86_fp80;
7193 types_index += 1;
7194 },
7195 .x87up => continue,
7196 .none => break,
7197 .memory => return .sret,
7198 .win_i128 => unreachable, // windows only
7199 .bool_vector_mask,
7200 .integer_per_element,
7201 .sse_per_element,
7202 .sse_sse_x87_per_qword,
7203 .sse_per_xword,
7204 .sse_per_yword,
7205 .sse_per_zword,
7206 => unreachable, // vectors already handled by `isScalar` above
7207 }
7208 }
7209 const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer});
7210 if (first_non_integer == null or classes[first_non_integer.?] == .none) {
7211 assert(first_non_integer orelse classes.len == types_index);
7212 switch (ip.indexToKey(ret_ty.toIntern())) {
7213 .struct_type => {
7214 const size = ret_ty.abiSize(zcu);
7215 assert(@divCeil(size, 8) == types_index);
7216 if (size % 8 > 0) {
7217 types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));
7218 }
7219 },
7220 else => {},
7221 }
7222 if (types_index == 1) return .{ .mem_cast = types_buffer[0] };
7616 var types_len: u32 = 0;
7617 for (classes, 0..) |class, class_index| switch (class) {
7618 .integer => {
7619 types_buffer[types_len] = try o.builder.intType(@min(8 * ret_ty.abiSize(zcu) - 64 * class_index, 64));
7620 types_len += 1;
7621 },
7622 .sse => {
7623 types_buffer[types_len] = .double;
7624 types_len += 1;
7625 },
7626 .sseup => {
7627 if (types_buffer[types_len - 1] == .double) {
7628 if (ret_ty.isVector(zcu)) return .by_val;
7629 types_buffer[types_len - 1] = .fp128;
7630 } else {
7631 types_buffer[types_len] = .double;
7632 types_len += 1;
7633 }
7634 },
7635 .float => {
7636 types_buffer[types_len] = .float;
7637 types_len += 1;
7638 },
7639 .float_combine => {
7640 types_buffer[types_len] = try o.builder.vectorType(.normal, 2, .float);
7641 types_len += 1;
7642 },
7643 .x87 => {
7644 if (types_len > 0 or classes[2] != .none) return .sret;
7645 types_buffer[types_len] = .x86_fp80;
7646 types_len += 1;
7647 },
7648 .x87up => continue,
7649 .none => break,
7650 .memory => return if (ret_ty.isVector(zcu)) .by_val else .sret,
7651 .win_i128 => unreachable, // windows only
7652 .bool_vector_mask,
7653 .integer_per_element,
7654 .sse_per_element,
7655 .sse_sse_x87_per_qword,
7656 .sse_per_xword,
7657 .sse_per_yword,
7658 .sse_per_zword,
7659 => return .by_val,
7660 };
7661 if (types_len > 1) return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_len]) };
7662 if (!isByRef(ret_ty, zcu)) {
7663 const llvm_ty = try o.lowerType(ret_ty, .as_value);
7664 if (types_buffer[0] == llvm_ty) return .by_val;
7665 if (types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)) return .by_val;
7666 if (types_buffer[0] == .double and llvm_ty.isVector(&o.builder) and
7667 llvm_ty.vectorLen(&o.builder) == 1 and
7668 llvm_ty.scalarType(&o.builder) == .double) return .by_val;
72237669 }
7224 return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_index]) };
7670 return .{ .mem_cast = types_buffer[0] };
72257671}
72267672
72277673/// This function deliberately does not handle `_BitInt` because it typically
......@@ -7234,15 +7680,22 @@ pub fn ccAbiPromoteInt(cc: std.lang.CallingConvention, zcu: *Zcu, ty: Type) ?std
72347680 else => {},
72357681 }
72367682
7237 const ty_tag = ty.zigTypeTag(zcu);
7238 const int_info = switch (ty_tag) {
7239 .bool => Type.u1.intInfo(zcu),
7240 else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return null,
7241 };
7683 const target = zcu.getTarget();
7684 const int_info: std.lang.Type.Int = if (ty.toIntern() == .bool_type)
7685 .{ .signedness = .unsigned, .bits = 1 }
7686 else if (ty.isAbiInt(zcu))
7687 ty.intInfo(zcu)
7688 else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {
7689 else => unreachable,
7690 16, 32, 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
7691 .hard => return null,
7692 .soft => .{ .signedness = .unsigned, .bits = bits },
7693 },
7694 80, 128 => return null,
7695 } else return null;
72427696
7243 assert(int_info.bits == 0 or (int_info.bits == 1 and ty_tag == .bool) or std.math.isPowerOfTwo(int_info.bits));
7697 assert(int_info.bits == 0 or (int_info.bits == 1 and ty.toIntern() == .bool_type) or std.math.isPowerOfTwo(int_info.bits));
72447698
7245 const target = zcu.getTarget();
72467699 return switch (target.cpu.arch) {
72477700 .aarch64,
72487701 .aarch64_be,
......@@ -7338,15 +7791,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool {
73387791 .void,
73397792 .bool,
73407793 .int,
7341 .float,
73427794 .pointer,
73437795 .error_set,
73447796 .@"fn",
73457797 .@"enum",
7346 .vector,
73477798 .@"anyframe",
73487799 => false,
73497800
7801 .float, .vector => {
7802 const target = zcu.getTarget();
7803 const scalar_ty = ty.scalarType(zcu);
7804 return if (scalar_ty.isRuntimeFloat()) switch (scalar_ty.floatBits(target)) {
7805 else => unreachable,
7806 16, 32, 64 => false,
7807 80, 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
7808 .hard => false,
7809 .soft => true,
7810 },
7811 } else false;
7812 },
7813
73507814 .array,
73517815 .frame,
73527816 => ty.hasRuntimeBits(zcu),
......@@ -7392,7 +7856,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E
73927856fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value {
73937857 if (offset == 0) return ptr;
73947858 const o = fg.object;
7395 const llvm_usize_ty = try o.lowerType(.usize, .by_value);
7859 const llvm_usize_ty = try o.lowerType(.usize, .as_value);
73967860 const offset_val = try o.builder.intValue(llvm_usize_ty, offset);
73977861 return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, "");
73987862}
......@@ -7407,12 +7871,19 @@ fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u
74077871 return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, "");
74087872}
74097873
7410fn compilerRtIntBits(bits: u16) ?u16 {
7411 inline for (.{ 32, 64, 128 }) |b| {
7412 if (bits <= b) {
7413 return b;
7414 }
7415 }
7874fn compilerRtPromoteInt(int_info: InternPool.Key.IntType) ?Type {
7875 if (int_info.bits <= 32) return switch (int_info.signedness) {
7876 .signed => .i32,
7877 .unsigned => .u32,
7878 };
7879 if (int_info.bits <= 64) return switch (int_info.signedness) {
7880 .signed => .i64,
7881 .unsigned => .u64,
7882 };
7883 if (int_info.bits <= 128) return switch (int_info.signedness) {
7884 .signed => .i128,
7885 .unsigned => .u128,
7886 };
74167887 return null;
74177888}
74187889
......@@ -7471,13 +7942,21 @@ fn appendConstraints(
74717942}
74727943
74737944/// LLVM does not support all relevant intrinsics for all targets, so we
7474/// may need to manually generate a compiler-rt call.
7475fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool {
7476 return switch (scalar_ty.toIntern()) {
7477 .f16_type => llvm.backendSupportsF16(target),
7478 .f80_type => (target.cTypeBitSize(.longdouble) == 80) and llvm.backendSupportsF80(target),
7479 .f128_type => (target.cTypeBitSize(.longdouble) == 128) and llvm.backendSupportsF128(target),
7480 else => true,
7945/// may need to manually generate a compiler-rt call using a soft type.
7946fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool {
7947 if (!scalar_ty.isRuntimeFloat()) return true;
7948 const bits = scalar_ty.floatBits(target);
7949 // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides
7950 // that it is a much better idea to just emit a call to the entirely wrong function as
7951 // a fallback. We wouldn't want any linker errors when trying to perform an operation
7952 // that isn't actually implemented anywhere, now would we!
7953 if (bits == 128 and target.cpu.arch.isX86() and !target.abi.isGnu()) return switch (kind) {
7954 .compiler_rt => true,
7955 .libc => false,
7956 };
7957 return switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
7958 .hard => true,
7959 .soft => false,
74817960 };
74827961}
74837962
......@@ -7823,12 +8302,14 @@ const Builder = std.zig.llvm.Builder;
78238302const assert = std.debug.assert;
78248303const math = std.math;
78258304
7826const x86_64_abi = @import("../x86_64/abi.zig");
7827const wasm_c_abi = @import("../wasm/abi.zig");
78288305const aarch64_c_abi = @import("../aarch64/abi.zig");
78298306const arm_c_abi = @import("../arm/abi.zig");
7830const riscv_c_abi = @import("../riscv64/abi.zig");
8307const loongarch_c_abi = @import("../loongarch/abi.zig");
78318308const mips_c_abi = @import("../mips/abi.zig");
8309const riscv_c_abi = @import("../riscv64/abi.zig");
8310const s390x_c_abi = @import("../s390x/abi.zig");
8311const wasm_c_abi = @import("../wasm/abi.zig");
8312const x86_64_abi = @import("../x86_64/abi.zig");
78328313
78338314const Zcu = @import("../../Zcu.zig");
78348315const Air = @import("../../Air.zig");
src/codegen/loongarch/abi.zig created+133
......@@ -0,0 +1,133 @@
1const std = @import("std");
2const InternPool = @import("../../InternPool.zig");
3const Type = @import("../../Type.zig");
4const Zcu = @import("../../Zcu.zig");
5
6pub const Class = union(enum) {
7 ignored,
8 gar,
9 far,
10 member: Type,
11 member_pair: [2]Type,
12 memory_gar,
13 memory_gar_pair,
14 address,
15
16 fn combineMember(container_class: Class, member_class: Class, member_ty: Type) Class {
17 const second_member_ty = switch (member_class) {
18 .ignored => return container_class,
19 .gar, .far => member_ty,
20 .member => |second_member_ty| second_member_ty,
21 .member_pair, .memory_gar, .memory_gar_pair, .address => return .address,
22 };
23 return switch (container_class) {
24 .ignored => .{ .member = second_member_ty },
25 .gar, .far, .memory_gar, .memory_gar_pair => unreachable,
26 .member => |first_member_ty| .{ .member_pair = .{ first_member_ty, second_member_ty } },
27 .member_pair, .address => .address,
28 };
29 }
30};
31
32pub fn classifyType(ty: Type, zcu: *Zcu) Class {
33 return Classifier.init(zcu).classifyType(ty);
34}
35
36const Classifier = struct {
37 zcu: *Zcu,
38 target: *const std.Target,
39 grlen: u8,
40 frlen: u8,
41
42 fn init(zcu: *Zcu) Classifier {
43 const target = zcu.getTarget();
44 return .{
45 .zcu = zcu,
46 .target = target,
47 .grlen = switch (target.cpu.arch) {
48 else => unreachable,
49 .loongarch32 => 32,
50 .loongarch64 => 64,
51 },
52 .frlen = if (target.cpu.has(.loongarch, .d))
53 64
54 else if (target.cpu.has(.loongarch, .f))
55 32
56 else
57 0,
58 };
59 }
60
61 fn classifyType(c: Classifier, ty: Type) Class {
62 switch (ty.zigTypeTag(c.zcu)) {
63 .type,
64 .comptime_float,
65 .comptime_int,
66 .undefined,
67 .null,
68 .error_union,
69 .error_set,
70 .@"fn",
71 .@"opaque",
72 .frame,
73 .@"anyframe",
74 .enum_literal,
75 .spirv,
76 => unreachable,
77 .void, .noreturn => return .ignored,
78 .bool => return .gar,
79 .int, .@"enum" => {
80 const bits = ty.intInfo(c.zcu).bits;
81 if (bits == 0) return .ignored;
82 if (bits <= c.grlen) return .gar;
83 if (bits <= 2 * c.grlen) return .memory_gar_pair;
84 return .address;
85 },
86 .float => {
87 const bits = ty.floatBits(c.target);
88 if (bits <= c.frlen) return .far;
89 if (bits <= c.grlen) return .gar;
90 if (bits <= 2 * c.grlen) return .memory_gar_pair;
91 return .address;
92 },
93 .pointer, .optional => return .gar,
94 .array => {
95 var class: Class = .ignored;
96 const elem_ty = ty.childType(c.zcu);
97 const elem_class = c.classifyType(elem_ty);
98 for (0..std.math.lossyCast(usize, ty.arrayLen(c.zcu))) |_| {
99 class = class.combineMember(elem_class, elem_ty);
100 if (class == .address) break;
101 }
102 if (class != .address) return class;
103 },
104 .@"struct" => switch (ty.containerLayout(c.zcu)) {
105 .auto => unreachable,
106 .@"extern" => {
107 var class: Class = .ignored;
108 var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (c.zcu.typeToStruct(ty)) |loaded_struct|
109 loaded_struct.iterateRuntimeOrder(&c.zcu.intern_pool)
110 else
111 .{ .runtime_order = null, .fields_len = ty.structFieldCount(c.zcu), .next_index = 0 };
112 while (field_it.next()) |field_index| {
113 const field_ty = ty.fieldType(field_index, c.zcu);
114 class = class.combineMember(c.classifyType(field_ty), field_ty);
115 if (class == .address) break;
116 }
117 if (class != .address) return class;
118 },
119 .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)),
120 },
121 .@"union" => switch (ty.containerLayout(c.zcu)) {
122 .auto => unreachable,
123 .@"extern" => {},
124 .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)),
125 },
126 .vector => {},
127 }
128 const size = ty.abiSize(c.zcu);
129 if (size <= @divExact(c.grlen, 8)) return .memory_gar;
130 if (size <= @divExact(2 * c.grlen, 8)) return .memory_gar_pair;
131 return .address;
132 }
133};
src/codegen/mips/abi.zig+8-1
......@@ -38,7 +38,14 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
3838 return .byval;
3939 },
4040 .bool => return .byval,
41 .float => return .byval,
41 .float => return switch (ty.floatBits(target)) {
42 else => unreachable,
43 16, 32, 64 => .byval,
44 80, 128 => switch (max_direct_size) {
45 else => unreachable,
46 64 => .memory,
47 },
48 },
4249 .int, .@"enum", .error_set => {
4350 return .byval;
4451 },
src/codegen/riscv64/CodeGen.zig+2-2
......@@ -5036,7 +5036,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
50365036 .register_pair,
50375037 => {
50385038 if (ret_ty.isVector(zcu)) {
5039 const bit_size = ret_ty.totalVectorBits(zcu);
5039 const bit_size = ret_ty.bitSize(zcu);
50405040
50415041 // set the vtype to hold the entire vector's contents in a single element
50425042 try func.setVl(.zero, 0, .{
......@@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
68716871 // size to the total size of the vector, and vmv.x.s will work then
68726872 if (src_reg.class() == .vector) {
68736873 try func.setVl(.zero, 0, .{
6874 .vsew = switch (ty.totalVectorBits(zcu)) {
6874 .vsew = switch (ty.bitSize(zcu)) {
68756875 8 => .@"8",
68766876 16 => .@"16",
68776877 32 => .@"32",
src/codegen/riscv64/abi.zig+10-2
......@@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
5656 return .integer;
5757 },
5858 .bool => return .integer,
59 .float => return .byval,
6059 .int, .@"enum", .error_set => {
6160 const bit_size = ty.bitSize(zcu);
6261 if (bit_size > max_byval_size) return .memory;
6362 return .byval;
6463 },
64 .float => return switch (ty.floatBits(target)) {
65 else => unreachable,
66 16, 32, 64, 128 => .byval,
67 80 => switch (max_byval_size) {
68 else => unreachable,
69 64 => .memory,
70 128 => .double_integer,
71 },
72 },
6573 .vector => {
6674 const bit_size = ty.bitSize(zcu);
6775 if (bit_size > max_byval_size) return .memory;
......@@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass {
190198 },
191199 .vector => {
192200 // we pass vectors through integer registers if they are small enough to fit.
193 const vec_bits = ty.totalVectorBits(zcu);
201 const vec_bits = ty.bitSize(zcu);
194202 if (vec_bits <= 64) {
195203 result[0] = .integer;
196204 return result;
src/codegen/s390x/abi.zig created+92
......@@ -0,0 +1,92 @@
1const assert = std.debug.assert;
2const std = @import("std");
3const InternPool = @import("../../InternPool.zig");
4const Type = @import("../../Type.zig");
5const Zcu = @import("../../Zcu.zig");
6
7pub const Context = enum { ret, arg };
8
9pub const Class = enum {
10 none,
11 double_or_float,
12 vector,
13 simple,
14 simple_aggregate,
15 pointer,
16};
17
18pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class {
19 tag: switch (ty.zigTypeTag(zcu)) {
20 .type,
21 .comptime_float,
22 .comptime_int,
23 .undefined,
24 .null,
25 .error_union,
26 .error_set,
27 .@"fn",
28 .@"opaque",
29 .frame,
30 .@"anyframe",
31 .enum_literal,
32 .spirv,
33 => unreachable,
34 .void, .noreturn => return .none,
35 .bool => return .simple,
36 .int, .@"enum" => return switch (ty.intInfo(zcu).bits) {
37 0 => .none,
38 1...64 => .simple,
39 else => .pointer,
40 },
41 .float => switch (ty.floatBits(zcu.getTarget())) {
42 else => unreachable,
43 16, 32, 64 => return .double_or_float,
44 80 => {},
45 128 => return .pointer,
46 },
47 .pointer, .optional => return .simple,
48 .array => switch (ty.arrayLen(zcu)) {
49 0 => return .none,
50 1 => switch (context) {
51 .ret => {},
52 .arg => return classifyType(ty.childType(zcu), context, zcu),
53 },
54 else => {},
55 },
56 .@"struct", .@"union" => |tag| switch (ty.containerLayout(zcu)) {
57 .auto => unreachable,
58 .@"extern" => switch (context) {
59 .ret => {},
60 .arg => {
61 var class: Class = .none;
62 for (0..switch (tag) {
63 else => unreachable,
64 .@"struct" => ty.structFieldCount(zcu),
65 .@"union" => ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu),
66 }) |field_index| {
67 switch (tag) {
68 else => unreachable,
69 .@"struct" => if (ty.structFieldIsComptime(field_index, zcu)) continue,
70 .@"union" => {},
71 }
72 const field_class = classifyType(ty.fieldType(field_index, zcu), context, zcu);
73 if (field_class == .none) continue;
74 if (class != .none) break :tag;
75 class = field_class;
76 }
77 return class;
78 },
79 },
80 .@"packed" => return classifyType(ty.backingIntType(zcu), context, zcu),
81 },
82 .vector => return if (ty.abiSize(zcu) <= 16) .vector else .pointer,
83 }
84 return switch (ty.abiSize(zcu)) {
85 0 => .none,
86 1, 2, 4, 8 => switch (context) {
87 .ret => .pointer,
88 .arg => .simple_aggregate,
89 },
90 else => .pointer,
91 };
92}
src/codegen/wasm/CodeGen.zig+25-31
......@@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment;
2424const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
2525const errUnionErrorOffset = codegen.errUnionErrorOffset;
2626
27const target_util = @import("../../target.zig");
28const libcFloatPrefix = target_util.libcFloatPrefix;
29const libcFloatSuffix = target_util.libcFloatSuffix;
30const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
31const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
32
3327pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
3428 return comptime &.initMany(&.{
3529 .expand_bit_cast_safe,
......@@ -2515,15 +2509,15 @@ const IntType = struct {
25152509 .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() },
25162510 .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() },
25172511 .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() },
2518 .c_char => .{ .is_signed = cg.target.cCharSignedness() == .signed, .bits = cg.target.cTypeBitSize(.char) },
2519 .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short) },
2520 .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short) },
2521 .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int) },
2522 .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int) },
2523 .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long) },
2524 .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long) },
2525 .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong) },
2526 .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong) },
2512 .c_char => .{ .is_signed = cg.target.cCharSignedness().? == .signed, .bits = cg.target.cTypeBitSize(.char).? },
2513 .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short).? },
2514 .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short).? },
2515 .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int).? },
2516 .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int).? },
2517 .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long).? },
2518 .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long).? },
2519 .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong).? },
2520 .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong).? },
25272521 .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable,
25282522 .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable,
25292523 },
......@@ -4340,7 +4334,7 @@ fn floatRem(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
43404334 .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
43414335 .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
43424336 .f80 => return cg.callIntrinsic(.__fmodx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),
4343 .f128 => return cg.callIntrinsic(.fmodq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
4337 .f128 => return cg.callIntrinsic(.fmodf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
43444338 }
43454339}
43464340
......@@ -4376,7 +4370,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
43764370 .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
43774371 .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
43784372 .f80 => return cg.callIntrinsic(.__fmaxx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),
4379 .f128 => return cg.callIntrinsic(.fmaxq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
4373 .f128 => return cg.callIntrinsic(.fmaxf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
43804374 }
43814375}
43824376
......@@ -4387,7 +4381,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV
43874381 .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }),
43884382 .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }),
43894383 .f80 => return cg.callIntrinsic(.__fminx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }),
4390 .f128 => return cg.callIntrinsic(.fminq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
4384 .f128 => return cg.callIntrinsic(.fminf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }),
43914385 }
43924386}
43934387
......@@ -4405,7 +4399,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44054399 return .stack;
44064400 },
44074401 .f80 => return cg.callIntrinsic(.__sqrtx, &.{.f80_type}, Type.f80, &.{arg}),
4408 .f128 => return cg.callIntrinsic(.sqrtq, &.{.f128_type}, Type.f128, &.{arg}),
4402 .f128 => return cg.callIntrinsic(.sqrtf128, &.{.f128_type}, Type.f128, &.{arg}),
44094403 }
44104404}
44114405
......@@ -4415,7 +4409,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44154409 .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}),
44164410 .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}),
44174411 .f80 => return cg.callIntrinsic(.__sinx, &.{.f80_type}, Type.f80, &.{arg}),
4418 .f128 => return cg.callIntrinsic(.sinq, &.{.f128_type}, Type.f128, &.{arg}),
4412 .f128 => return cg.callIntrinsic(.sinf128, &.{.f128_type}, Type.f128, &.{arg}),
44194413 }
44204414}
44214415
......@@ -4425,7 +4419,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44254419 .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}),
44264420 .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}),
44274421 .f80 => return cg.callIntrinsic(.__cosx, &.{.f80_type}, Type.f80, &.{arg}),
4428 .f128 => return cg.callIntrinsic(.cosq, &.{.f128_type}, Type.f128, &.{arg}),
4422 .f128 => return cg.callIntrinsic(.cosf128, &.{.f128_type}, Type.f128, &.{arg}),
44294423 }
44304424}
44314425
......@@ -4435,7 +4429,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44354429 .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}),
44364430 .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}),
44374431 .f80 => return cg.callIntrinsic(.__tanx, &.{.f80_type}, Type.f80, &.{arg}),
4438 .f128 => return cg.callIntrinsic(.tanq, &.{.f128_type}, Type.f128, &.{arg}),
4432 .f128 => return cg.callIntrinsic(.tanf128, &.{.f128_type}, Type.f128, &.{arg}),
44394433 }
44404434}
44414435
......@@ -4445,7 +4439,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44454439 .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}),
44464440 .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}),
44474441 .f80 => return cg.callIntrinsic(.__expx, &.{.f80_type}, Type.f80, &.{arg}),
4448 .f128 => return cg.callIntrinsic(.expq, &.{.f128_type}, Type.f128, &.{arg}),
4442 .f128 => return cg.callIntrinsic(.expf128, &.{.f128_type}, Type.f128, &.{arg}),
44494443 }
44504444}
44514445
......@@ -4455,7 +4449,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44554449 .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}),
44564450 .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}),
44574451 .f80 => return cg.callIntrinsic(.__exp2x, &.{.f80_type}, Type.f80, &.{arg}),
4458 .f128 => return cg.callIntrinsic(.exp2q, &.{.f128_type}, Type.f128, &.{arg}),
4452 .f128 => return cg.callIntrinsic(.exp2f128, &.{.f128_type}, Type.f128, &.{arg}),
44594453 }
44604454}
44614455
......@@ -4465,7 +4459,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44654459 .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}),
44664460 .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}),
44674461 .f80 => return cg.callIntrinsic(.__logx, &.{.f80_type}, Type.f80, &.{arg}),
4468 .f128 => return cg.callIntrinsic(.logq, &.{.f128_type}, Type.f128, &.{arg}),
4462 .f128 => return cg.callIntrinsic(.logf128, &.{.f128_type}, Type.f128, &.{arg}),
44694463 }
44704464}
44714465
......@@ -4475,7 +4469,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44754469 .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}),
44764470 .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}),
44774471 .f80 => return cg.callIntrinsic(.__log2x, &.{.f80_type}, Type.f80, &.{arg}),
4478 .f128 => return cg.callIntrinsic(.log2q, &.{.f128_type}, Type.f128, &.{arg}),
4472 .f128 => return cg.callIntrinsic(.log2f128, &.{.f128_type}, Type.f128, &.{arg}),
44794473 }
44804474}
44814475
......@@ -4485,7 +4479,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
44854479 .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}),
44864480 .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}),
44874481 .f80 => return cg.callIntrinsic(.__log10x, &.{.f80_type}, Type.f80, &.{arg}),
4488 .f128 => return cg.callIntrinsic(.log10q, &.{.f128_type}, Type.f128, &.{arg}),
4482 .f128 => return cg.callIntrinsic(.log10f128, &.{.f128_type}, Type.f128, &.{arg}),
44894483 }
44904484}
44914485
......@@ -4503,7 +4497,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45034497 return .stack;
45044498 },
45054499 .f80 => return cg.callIntrinsic(.__floorx, &.{.f80_type}, Type.f80, &.{arg}),
4506 .f128 => return cg.callIntrinsic(.floorq, &.{.f128_type}, Type.f128, &.{arg}),
4500 .f128 => return cg.callIntrinsic(.floorf128, &.{.f128_type}, Type.f128, &.{arg}),
45074501 }
45084502}
45094503
......@@ -4521,7 +4515,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45214515 return .stack;
45224516 },
45234517 .f80 => return cg.callIntrinsic(.__ceilx, &.{.f80_type}, Type.f80, &.{arg}),
4524 .f128 => return cg.callIntrinsic(.ceilq, &.{.f128_type}, Type.f128, &.{arg}),
4518 .f128 => return cg.callIntrinsic(.ceilf128, &.{.f128_type}, Type.f128, &.{arg}),
45254519 }
45264520}
45274521
......@@ -4539,7 +4533,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45394533 return .stack;
45404534 },
45414535 .f80 => return cg.callIntrinsic(.__roundx, &.{.f80_type}, Type.f80, &.{arg}),
4542 .f128 => return cg.callIntrinsic(.roundq, &.{.f128_type}, Type.f128, &.{arg}),
4536 .f128 => return cg.callIntrinsic(.roundf128, &.{.f128_type}, Type.f128, &.{arg}),
45434537 }
45444538}
45454539
......@@ -4557,7 +4551,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
45574551 return .stack;
45584552 },
45594553 .f80 => return cg.callIntrinsic(.__truncx, &.{.f80_type}, Type.f80, &.{arg}),
4560 .f128 => return cg.callIntrinsic(.truncq, &.{.f128_type}, Type.f128, &.{arg}),
4554 .f128 => return cg.callIntrinsic(.truncf128, &.{.f128_type}, Type.f128, &.{arg}),
45614555 }
45624556}
45634557
src/codegen/wasm/Mir.zig+18-18
......@@ -991,48 +991,48 @@ pub const Intrinsic = enum(u32) {
991991 __udivti3,
992992 __umodei5,
993993 __umodti3,
994 ceilq,
994 ceilf128,
995995 cos,
996996 cosf,
997 cosq,
997 cosf128,
998998 exp,
999999 exp2,
10001000 exp2f,
1001 exp2q,
1001 exp2f128,
10021002 expf,
1003 expq,
1004 fabsq,
1005 floorq,
1003 expf128,
1004 fabsf128,
1005 floorf128,
10061006 fma,
10071007 fmaf,
1008 fmaq,
1008 fmaf128,
10091009 fmax,
10101010 fmaxf,
1011 fmaxq,
1011 fmaxf128,
10121012 fmin,
10131013 fminf,
1014 fminq,
1014 fminf128,
10151015 fmod,
10161016 fmodf,
1017 fmodq,
1017 fmodf128,
10181018 log,
10191019 log10,
10201020 log10f,
1021 log10q,
1021 log10f128,
10221022 log2,
10231023 log2f,
1024 log2q,
1024 log2f128,
10251025 logf,
1026 logq,
1027 roundq,
1026 logf128,
1027 roundf128,
10281028 sin,
10291029 sinf,
1030 sinq,
1031 sqrtq,
1030 sinf128,
1031 sqrtf128,
10321032 tan,
10331033 tanf,
1034 tanq,
1035 truncq,
1034 tanf128,
1035 truncf128,
10361036 memcpy,
10371037 memmove,
10381038 memset,
src/codegen/wasm/abi.zig+5-1
......@@ -25,7 +25,11 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
2525 assert(ty.hasRuntimeBits(zcu));
2626 switch (ty.zigTypeTag(zcu)) {
2727 .int, .@"enum", .error_set => return .{ .direct = ty },
28 .float => return .{ .direct = ty },
28 .float => return switch (ty.floatBits(zcu.getTarget())) {
29 else => unreachable,
30 16, 32, 64, 128 => .{ .direct = ty },
31 80 => .indirect,
32 },
2933 .bool => return .{ .direct = ty },
3034 .vector => return .{ .direct = ty },
3135 .array => return .indirect,
src/codegen/x86_64/CodeGen.zig+157-285
......@@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3443634436 .call_frame = .{ .alignment = .@"16" },
3443734437 .extra_temps = .{
3443834438 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34439 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34439 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3444034440 .unused,
3444134441 .unused,
3444234442 .unused,
......@@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3447034470 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3447134471 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3447234472 .{ .type = .f128, .kind = .mem },
34473 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34473 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3447434474 .unused,
3447534475 .unused,
3447634476 .unused,
......@@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3450534505 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3450634506 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3450734507 .{ .type = .f128, .kind = .mem },
34508 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34508 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3450934509 .unused,
3451034510 .unused,
3451134511 .unused,
......@@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3454034540 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3454134541 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3454234542 .{ .type = .f128, .kind = .mem },
34543 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34543 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3454434544 .unused,
3454534545 .unused,
3454634546 .unused,
......@@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3457534575 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3457634576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3457734577 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34578 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34578 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3457934579 .unused,
3458034580 .unused,
3458134581 .unused,
......@@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3461234612 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3461334613 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3461434614 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34615 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34615 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3461634616 .unused,
3461734617 .unused,
3461834618 .unused,
......@@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3464934649 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3465034650 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3465134651 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34652 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34652 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3465334653 .unused,
3465434654 .unused,
3465534655 .unused,
......@@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3468834688 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3468934689 .{ .type = .f128, .kind = .mem },
3469034690 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34691 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34691 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3469234692 .unused,
3469334693 .unused,
3469434694 .unused,
......@@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3472734727 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3472834728 .{ .type = .f128, .kind = .mem },
3472934729 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34730 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34730 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3473134731 .unused,
3473234732 .unused,
3473334733 .unused,
......@@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3476634766 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3476734767 .{ .type = .f128, .kind = .mem },
3476834768 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
34769 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
34769 .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } },
3477034770 .unused,
3477134771 .unused,
3477234772 .unused,
......@@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3596035960 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3596135961 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3596235962 else => unreachable,
35963 .zero => "truncq",
35964 .down => "floorq",
35963 .zero => "truncf128",
35964 .down => "floorf128",
3596535965 } } },
3596635966 .unused,
3596735967 .unused,
......@@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3599835998 .{ .type = .f128, .kind = .mem },
3599935999 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3600036000 else => unreachable,
36001 .zero => "truncq",
36002 .down => "floorq",
36001 .zero => "truncf128",
36002 .down => "floorf128",
3600336003 } } },
3600436004 .unused,
3600536005 .unused,
......@@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3603736037 .{ .type = .f128, .kind = .mem },
3603836038 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3603936039 else => unreachable,
36040 .zero => "truncq",
36041 .down => "floorq",
36040 .zero => "truncf128",
36041 .down => "floorf128",
3604236042 } } },
3604336043 .unused,
3604436044 .unused,
......@@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3607636076 .{ .type = .f128, .kind = .mem },
3607736077 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3607836078 else => unreachable,
36079 .zero => "truncq",
36080 .down => "floorq",
36079 .zero => "truncf128",
36080 .down => "floorf128",
3608136081 } } },
3608236082 .unused,
3608336083 .unused,
......@@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3611536115 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3611636116 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3611736117 else => unreachable,
36118 .zero => "truncq",
36119 .down => "floorq",
36118 .zero => "truncf128",
36119 .down => "floorf128",
3612036120 } } },
3612136121 .unused,
3612236122 .unused,
......@@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3615636156 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3615736157 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3615836158 else => unreachable,
36159 .zero => "truncq",
36160 .down => "floorq",
36159 .zero => "truncf128",
36160 .down => "floorf128",
3616136161 } } },
3616236162 .unused,
3616336163 .unused,
......@@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3619736197 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3619836198 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3619936199 else => unreachable,
36200 .zero => "truncq",
36201 .down => "floorq",
36200 .zero => "truncf128",
36201 .down => "floorf128",
3620236202 } } },
3620336203 .unused,
3620436204 .unused,
......@@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3624036240 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3624136241 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3624236242 else => unreachable,
36243 .zero => "truncq",
36244 .down => "floorq",
36243 .zero => "truncf128",
36244 .down => "floorf128",
3624536245 } } },
3624636246 .unused,
3624736247 .unused,
......@@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3628336283 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3628436284 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3628536285 else => unreachable,
36286 .zero => "truncq",
36287 .down => "floorq",
36286 .zero => "truncf128",
36287 .down => "floorf128",
3628836288 } } },
3628936289 .unused,
3629036290 .unused,
......@@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3632636326 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3632736327 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3632836328 else => unreachable,
36329 .zero => "truncq",
36330 .down => "floorq",
36329 .zero => "truncf128",
36330 .down => "floorf128",
3633136331 } } },
3633236332 .unused,
3633336333 .unused,
......@@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3769137691 .call_frame = .{ .alignment = .@"16" },
3769237692 .extra_temps = .{
3769337693 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37694 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37694 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3769537695 .unused,
3769637696 .unused,
3769737697 .unused,
......@@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3772537725 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3772637726 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3772737727 .{ .type = .f128, .kind = .mem },
37728 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37728 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3772937729 .unused,
3773037730 .unused,
3773137731 .unused,
......@@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3776037760 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3776137761 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3776237762 .{ .type = .f128, .kind = .mem },
37763 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37763 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3776437764 .unused,
3776537765 .unused,
3776637766 .unused,
......@@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3779537795 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3779637796 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3779737797 .{ .type = .f128, .kind = .mem },
37798 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37798 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3779937799 .unused,
3780037800 .unused,
3780137801 .unused,
......@@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3783037830 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3783137831 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3783237832 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37833 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37833 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3783437834 .unused,
3783537835 .unused,
3783637836 .unused,
......@@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3786737867 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3786837868 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3786937869 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37870 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37870 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3787137871 .unused,
3787237872 .unused,
3787337873 .unused,
......@@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3790437904 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3790537905 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
3790637906 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
37907 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37907 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3790837908 .unused,
3790937909 .unused,
3791037910 .unused,
......@@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3794337943 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3794437944 .{ .type = .f128, .kind = .mem },
3794537945 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37946 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37946 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3794737947 .unused,
3794837948 .unused,
3794937949 .unused,
......@@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3798237982 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3798337983 .{ .type = .f128, .kind = .mem },
3798437984 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
37985 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
37985 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3798637986 .unused,
3798737987 .unused,
3798837988 .unused,
......@@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3802138021 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3802238022 .{ .type = .f128, .kind = .mem },
3802338023 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
38024 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
38024 .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } },
3802538025 .unused,
3802638026 .unused,
3802738027 .unused,
......@@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3955839558 },
3955939559 .call_frame = .{ .alignment = .@"16" },
3956039560 .extra_temps = .{
39561 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39561 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3956239562 .unused,
3956339563 .unused,
3956439564 .unused,
......@@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3959039590 .extra_temps = .{
3959139591 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3959239592 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39593 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39593 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3959439594 .unused,
3959539595 .unused,
3959639596 .unused,
......@@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3962339623 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3962439624 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3962539625 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39626 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39626 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3962739627 .unused,
3962839628 .unused,
3962939629 .unused,
......@@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3965939659 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3966039660 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3966139661 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39662 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39662 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3966339663 .unused,
3966439664 .unused,
3966539665 .unused,
......@@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3969539695 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3969639696 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3969739697 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39698 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39698 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3969939699 .unused,
3970039700 .unused,
3970139701 .unused,
......@@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3973139731 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3973239732 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3973339733 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39734 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39734 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3973539735 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3973639736 .unused,
3973739737 .unused,
......@@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3976739767 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3976839768 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3976939769 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39770 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39770 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3977139771 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3977239772 .unused,
3977339773 .unused,
......@@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3980339803 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3980439804 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3980539805 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
39806 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
39806 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
3980739807 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
3980839808 .unused,
3980939809 .unused,
......@@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4280342803 .call_frame = .{ .alignment = .@"16" },
4280442804 .extra_temps = .{
4280542805 .{ .type = .f128, .kind = .mem },
42806 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42806 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4280742807 .{ .type = .u64, .kind = .{ .reg = .rcx } },
4280842808 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4280942809 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4284942849 .call_frame = .{ .alignment = .@"16" },
4285042850 .extra_temps = .{
4285142851 .{ .type = .f128, .kind = .mem },
42852 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42852 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4285342853 .{ .type = .u64, .kind = .{ .reg = .rcx } },
4285442854 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4285542855 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4289542895 .call_frame = .{ .alignment = .@"16" },
4289642896 .extra_temps = .{
4289742897 .{ .type = .f128, .kind = .mem },
42898 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42898 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4289942899 .{ .type = .u64, .kind = .{ .reg = .rcx } },
4290042900 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4290142901 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4294242942 .call_frame = .{ .alignment = .@"16" },
4294342943 .extra_temps = .{
4294442944 .{ .type = .f128, .kind = .mem },
42945 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42945 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4294642946 .{ .type = .u64, .kind = .{ .reg = .rdx } },
4294742947 .{ .type = .f128, .kind = .mem },
4294842948 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4298442984 .extra_temps = .{
4298542985 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4298642986 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
42987 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
42987 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4298842988 .{ .type = .f128, .kind = .mem },
4298942989 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4299042990 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4302943029 .extra_temps = .{
4303043030 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4303143031 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43032 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43032 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4303343033 .{ .type = .f128, .kind = .mem },
4303443034 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4303543035 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4307443074 .extra_temps = .{
4307543075 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4307643076 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43077 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43077 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4307843078 .{ .type = .f128, .kind = .mem },
4307943079 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4308043080 .{ .type = .u64, .kind = .{ .reg = .rax } },
......@@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4312043120 .extra_temps = .{
4312143121 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4312243122 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43123 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43123 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4312443124 .{ .type = .f128, .kind = .mem },
4312543125 .{ .type = .usize, .kind = .{ .reg = .rax } },
4312643126 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
......@@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4316443164 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4316543165 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4316643166 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43167 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43167 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4316843168 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4316943169 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4317043170 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4321143211 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4321243212 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4321343213 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43214 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43214 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4321543215 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4321643216 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4321743217 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4325843258 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4325943259 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4326043260 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43261 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43261 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4326243262 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4326343263 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4326443264 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4330643306 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4330743307 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4330843308 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
43309 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
43309 .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } },
4331043310 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4331143311 .{ .type = .f128, .kind = .mem },
4331243312 .{ .type = .f128, .kind = .{ .reg = .rax } },
......@@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4762347623 },
4762447624 .call_frame = .{ .alignment = .@"16" },
4762547625 .extra_temps = .{
47626 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47626 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4762747627 .unused,
4762847628 .unused,
4762947629 .unused,
......@@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4765547655 .extra_temps = .{
4765647656 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4765747657 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47658 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47658 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4765947659 .unused,
4766047660 .unused,
4766147661 .unused,
......@@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4768847688 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4768947689 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4769047690 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47691 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47691 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4769247692 .unused,
4769347693 .unused,
4769447694 .unused,
......@@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4772447724 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4772547725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4772647726 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47727 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47727 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4772847728 .unused,
4772947729 .unused,
4773047730 .unused,
......@@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4776047760 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4776147761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4776247762 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47763 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47763 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4776447764 .unused,
4776547765 .unused,
4776647766 .unused,
......@@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4779647796 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4779747797 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4779847798 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47799 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47799 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4780047800 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4780147801 .unused,
4780247802 .unused,
......@@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4783247832 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4783347833 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4783447834 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47835 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47835 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4783647836 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4783747837 .unused,
4783847838 .unused,
......@@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4786847868 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4786947869 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4787047870 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
47871 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
47871 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
4787247872 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
4787347873 .unused,
4787447874 .unused,
......@@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5192651926 },
5192751927 .call_frame = .{ .alignment = .@"16" },
5192851928 .extra_temps = .{
51929 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
51929 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5193051930 .unused,
5193151931 .unused,
5193251932 .unused,
......@@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5195851958 .extra_temps = .{
5195951959 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5196051960 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
51961 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
51961 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5196251962 .unused,
5196351963 .unused,
5196451964 .unused,
......@@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5199151991 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
5199251992 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5199351993 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
51994 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
51994 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5199551995 .unused,
5199651996 .unused,
5199751997 .unused,
......@@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5202752027 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
5202852028 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5202952029 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52030 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52030 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5203152031 .unused,
5203252032 .unused,
5203352033 .unused,
......@@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5206352063 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
5206452064 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5206552065 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52066 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52066 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5206752067 .unused,
5206852068 .unused,
5206952069 .unused,
......@@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5209952099 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
5210052100 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5210152101 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52102 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52102 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5210352103 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5210452104 .unused,
5210552105 .unused,
......@@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5213552135 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
5213652136 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5213752137 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52138 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52138 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5213952139 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5214052140 .unused,
5214152141 .unused,
......@@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
5217152171 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
5217252172 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5217352173 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
52174 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
52174 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
5217552175 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
5217652176 .unused,
5217752177 .unused,
......@@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7645776457 },
7645876458 .call_frame = .{ .alignment = .@"16" },
7645976459 .extra_temps = .{
76460 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76460 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7646176461 .unused,
7646276462 .unused,
7646376463 .unused,
......@@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7648476484 .call_frame = .{ .alignment = .@"16" },
7648576485 .extra_temps = .{
7648676486 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76487 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76487 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7648876488 .unused,
7648976489 .unused,
7649076490 .unused,
......@@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7651276512 .extra_temps = .{
7651376513 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7651476514 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76515 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76515 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7651676516 .unused,
7651776517 .unused,
7651876518 .unused,
......@@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7654376543 .extra_temps = .{
7654476544 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7654576545 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76546 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76546 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7654776547 .unused,
7654876548 .unused,
7654976549 .unused,
......@@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7657476574 .extra_temps = .{
7657576575 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7657676576 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76577 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76577 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7657876578 .unused,
7657976579 .unused,
7658076580 .unused,
......@@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7660576605 .extra_temps = .{
7660676606 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7660776607 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76608 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76608 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7660976609 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7661076610 .unused,
7661176611 .unused,
......@@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7663676636 .extra_temps = .{
7663776637 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7663876638 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76639 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76639 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7664076640 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7664176641 .unused,
7664276642 .unused,
......@@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7666776667 .extra_temps = .{
7666876668 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7666976669 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
76670 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
76670 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } },
7667176671 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7667276672 .unused,
7667376673 .unused,
......@@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7730677306 },
7730777307 .call_frame = .{ .alignment = .@"16" },
7730877308 .extra_temps = .{
77309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7731077310 .unused,
7731177311 .unused,
7731277312 .unused,
......@@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7733377333 .call_frame = .{ .alignment = .@"16" },
7733477334 .extra_temps = .{
7733577335 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77336 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77336 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7733777337 .unused,
7733877338 .unused,
7733977339 .unused,
......@@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7736177361 .extra_temps = .{
7736277362 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7736377363 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77364 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77364 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7736577365 .unused,
7736677366 .unused,
7736777367 .unused,
......@@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7739277392 .extra_temps = .{
7739377393 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7739477394 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77395 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77395 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7739677396 .unused,
7739777397 .unused,
7739877398 .unused,
......@@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7742377423 .extra_temps = .{
7742477424 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7742577425 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77426 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77426 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7742777427 .unused,
7742877428 .unused,
7742977429 .unused,
......@@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7745477454 .extra_temps = .{
7745577455 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7745677456 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77457 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77457 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7745877458 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7745977459 .unused,
7746077460 .unused,
......@@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7748577485 .extra_temps = .{
7748677486 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7748777487 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77488 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77488 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7748977489 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7749077490 .unused,
7749177491 .unused,
......@@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7751677516 .extra_temps = .{
7751777517 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7751877518 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
77519 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
77519 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } },
7752077520 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
7752177521 .unused,
7752277522 .unused,
......@@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8015580155 .extra_temps = .{
8015680156 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8015780157 else => unreachable,
80158 .down => "floorq",
80159 .up => "ceilq",
80160 .zero => "truncq",
80158 .down => "floorf128",
80159 .up => "ceilf128",
80160 .zero => "truncf128",
8016180161 } } },
8016280162 .unused,
8016380163 .unused,
......@@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8018780187 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8018880188 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8018980189 else => unreachable,
80190 .down => "floorq",
80191 .up => "ceilq",
80192 .zero => "truncq",
80190 .down => "floorf128",
80191 .up => "ceilf128",
80192 .zero => "truncf128",
8019380193 } } },
8019480194 .unused,
8019580195 .unused,
......@@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8022080220 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8022180221 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8022280222 else => unreachable,
80223 .down => "floorq",
80224 .up => "ceilq",
80225 .zero => "truncq",
80223 .down => "floorf128",
80224 .up => "ceilf128",
80225 .zero => "truncf128",
8022680226 } } },
8022780227 .unused,
8022880228 .unused,
......@@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8025680256 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8025780257 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8025880258 else => unreachable,
80259 .down => "floorq",
80260 .up => "ceilq",
80261 .zero => "truncq",
80259 .down => "floorf128",
80260 .up => "ceilf128",
80261 .zero => "truncf128",
8026280262 } } },
8026380263 .unused,
8026480264 .unused,
......@@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8029280292 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8029380293 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8029480294 else => unreachable,
80295 .down => "floorq",
80296 .up => "ceilq",
80297 .zero => "truncq",
80295 .down => "floorf128",
80296 .up => "ceilf128",
80297 .zero => "truncf128",
8029880298 } } },
8029980299 .unused,
8030080300 .unused,
......@@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8032880328 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8032980329 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8033080330 else => unreachable,
80331 .down => "floorq",
80332 .up => "ceilq",
80333 .zero => "truncq",
80331 .down => "floorf128",
80332 .up => "ceilf128",
80333 .zero => "truncf128",
8033480334 } } },
8033580335 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8033680336 .unused,
......@@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8036480364 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8036580365 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8036680366 else => unreachable,
80367 .down => "floorq",
80368 .up => "ceilq",
80369 .zero => "truncq",
80367 .down => "floorf128",
80368 .up => "ceilf128",
80369 .zero => "truncf128",
8037080370 } } },
8037180371 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8037280372 .unused,
......@@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8040080400 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8040180401 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
8040280402 else => unreachable,
80403 .down => "floorq",
80404 .up => "ceilq",
80405 .zero => "truncq",
80403 .down => "floorf128",
80404 .up => "ceilf128",
80405 .zero => "truncf128",
8040680406 } } },
8040780407 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
8040880408 .unused,
......@@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
125531125531 .{ ._, ._, .call, .tmp1d, ._, ._, ._ },
125532125532 } },
125533125533 }, .{
125534 .required_cc_abi = .sysv64,
125535125534 .required_features = .{ .sse, null, null, null },
125536125535 .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any },
125537125536 .dst_constraints = .{ .{ .float = .xword }, .any },
......@@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
125557125556 .each = .{ .once = &.{
125558125557 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },
125559125558 } },
125560 }, .{
125561 .required_cc_abi = .win64,
125562 .required_features = .{ .sse, null, null, null },
125563 .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any },
125564 .dst_constraints = .{ .{ .float = .xword }, .any },
125565 .patterns = &.{
125566 .{ .src = .{ .to_mem, .none, .none } },
125567 },
125568 .call_frame = .{ .alignment = .@"16" },
125569 .extra_temps = .{
125570 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
125571 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
125572 .unused,
125573 .unused,
125574 .unused,
125575 .unused,
125576 .unused,
125577 .unused,
125578 .unused,
125579 .unused,
125580 .unused,
125581 },
125582 .dst_temps = .{ .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } }, .unused },
125583 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
125584 .each = .{ .once = &.{
125585 .{ ._, ._, .lea, .tmp0p, .mem(.src0), ._, ._ },
125586 .{ ._, ._, .call, .tmp1d, ._, ._, ._ },
125587 } },
125588125559 }, .{
125589125560 .required_features = .{ .@"64bit", .sse, null, null },
125590125561 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any },
......@@ -126791,7 +126762,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126791126762 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126792126763 } },
126793126764 }, .{
126794 .required_cc_abi = .sysv64,
126795126765 .required_features = .{ .avx, null, null, null },
126796126766 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126797126767 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
......@@ -126824,39 +126794,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126824126794 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126825126795 } },
126826126796 }, .{
126827 .required_cc_abi = .win64,
126828 .required_features = .{ .avx, null, null, null },
126829 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126830 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
126831 .patterns = &.{
126832 .{ .src = .{ .to_mem, .none, .none } },
126833 },
126834 .call_frame = .{ .alignment = .@"16" },
126835 .extra_temps = .{
126836 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
126837 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126838 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
126839 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126840 .unused,
126841 .unused,
126842 .unused,
126843 .unused,
126844 .unused,
126845 .unused,
126846 .unused,
126847 },
126848 .dst_temps = .{ .mem, .unused },
126849 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
126850 .each = .{ .once = &.{
126851 .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ },
126852 .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ },
126853 .{ ._, ._, .call, .tmp2d, ._, ._, ._ },
126854 .{ ._, .v_dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ },
126855 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126856 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126857 } },
126858 }, .{
126859 .required_cc_abi = .sysv64,
126860126797 .required_features = .{ .sse2, null, null, null },
126861126798 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126862126799 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
......@@ -126889,39 +126826,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126889126826 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126890126827 } },
126891126828 }, .{
126892 .required_cc_abi = .win64,
126893 .required_features = .{ .sse2, null, null, null },
126894 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126895 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
126896 .patterns = &.{
126897 .{ .src = .{ .to_mem, .none, .none } },
126898 },
126899 .call_frame = .{ .alignment = .@"16" },
126900 .extra_temps = .{
126901 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
126902 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126903 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
126904 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126905 .unused,
126906 .unused,
126907 .unused,
126908 .unused,
126909 .unused,
126910 .unused,
126911 .unused,
126912 },
126913 .dst_temps = .{ .mem, .unused },
126914 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
126915 .each = .{ .once = &.{
126916 .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ },
126917 .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ },
126918 .{ ._, ._, .call, .tmp2d, ._, ._, ._ },
126919 .{ ._, ._dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ },
126920 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126921 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126922 } },
126923 }, .{
126924 .required_cc_abi = .sysv64,
126925126829 .required_features = .{ .sse, null, null, null },
126926126830 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126927126831 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
......@@ -126953,38 +126857,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
126953126857 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126954126858 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126955126859 } },
126956 }, .{
126957 .required_cc_abi = .win64,
126958 .required_features = .{ .sse, null, null, null },
126959 .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any },
126960 .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any },
126961 .patterns = &.{
126962 .{ .src = .{ .to_mem, .none, .none } },
126963 },
126964 .call_frame = .{ .alignment = .@"16" },
126965 .extra_temps = .{
126966 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
126967 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126968 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
126969 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
126970 .unused,
126971 .unused,
126972 .unused,
126973 .unused,
126974 .unused,
126975 .unused,
126976 .unused,
126977 },
126978 .dst_temps = .{ .mem, .unused },
126979 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
126980 .each = .{ .once = &.{
126981 .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ },
126982 .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ },
126983 .{ ._, ._, .call, .tmp2d, ._, ._, ._ },
126984 .{ ._, ._ps, .mova, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ },
126985 .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ },
126986 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
126987 } },
126988126860 }, .{
126989126861 .required_features = .{ .@"64bit", .avx, null, null },
126990126862 .src_constraints = .{ .{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any },
......@@ -142552,7 +142424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142552142424 .extra_temps = .{
142553142425 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142554142426 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142555 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142427 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142556142428 .unused,
142557142429 .unused,
142558142430 .unused,
......@@ -142584,7 +142456,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142584142456 .extra_temps = .{
142585142457 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142586142458 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142587 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142459 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142588142460 .unused,
142589142461 .unused,
142590142462 .unused,
......@@ -142616,7 +142488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142616142488 .extra_temps = .{
142617142489 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142618142490 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142619 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142491 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142620142492 .unused,
142621142493 .unused,
142622142494 .unused,
......@@ -142649,7 +142521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142649142521 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142650142522 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142651142523 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142652 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142524 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142653142525 .{ .type = .f128, .kind = .mem },
142654142526 .unused,
142655142527 .unused,
......@@ -142683,7 +142555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142683142555 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142684142556 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142685142557 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142686 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142558 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142687142559 .{ .type = .f128, .kind = .mem },
142688142560 .unused,
142689142561 .unused,
......@@ -142717,7 +142589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142717142589 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142718142590 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
142719142591 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
142720 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
142592 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
142721142593 .{ .type = .f128, .kind = .mem },
142722142594 .unused,
142723142595 .unused,
......@@ -152785,7 +152657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152785152657 .extra_temps = .{
152786152658 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152787152659 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152788 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152660 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152789152661 .unused,
152790152662 .unused,
152791152663 .unused,
......@@ -152817,7 +152689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152817152689 .extra_temps = .{
152818152690 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152819152691 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152820 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152692 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152821152693 .unused,
152822152694 .unused,
152823152695 .unused,
......@@ -152849,7 +152721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152849152721 .extra_temps = .{
152850152722 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152851152723 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152852 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152724 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152853152725 .unused,
152854152726 .unused,
152855152727 .unused,
......@@ -152882,7 +152754,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152882152754 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152883152755 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152884152756 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152885 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152757 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152886152758 .{ .type = .f128, .kind = .mem },
152887152759 .unused,
152888152760 .unused,
......@@ -152916,7 +152788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152916152788 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152917152789 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152918152790 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152919 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152791 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152920152792 .{ .type = .f128, .kind = .mem },
152921152793 .unused,
152922152794 .unused,
......@@ -152950,7 +152822,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152950152822 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152951152823 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
152952152824 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
152953 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
152825 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
152954152826 .{ .type = .f128, .kind = .mem },
152955152827 .unused,
152956152828 .unused,
......@@ -163019,7 +162891,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163019162891 .extra_temps = .{
163020162892 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163021162893 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163022 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162894 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163023162895 .unused,
163024162896 .unused,
163025162897 .unused,
......@@ -163051,7 +162923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163051162923 .extra_temps = .{
163052162924 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163053162925 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163054 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162926 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163055162927 .unused,
163056162928 .unused,
163057162929 .unused,
......@@ -163083,7 +162955,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163083162955 .extra_temps = .{
163084162956 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163085162957 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163086 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162958 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163087162959 .unused,
163088162960 .unused,
163089162961 .unused,
......@@ -163116,7 +162988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163116162988 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163117162989 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163118162990 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163119 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
162991 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163120162992 .{ .type = .f128, .kind = .mem },
163121162993 .unused,
163122162994 .unused,
......@@ -163150,7 +163022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163150163022 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163151163023 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163152163024 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163153 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
163025 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163154163026 .{ .type = .f128, .kind = .mem },
163155163027 .unused,
163156163028 .unused,
......@@ -163184,7 +163056,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163184163056 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
163185163057 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
163186163058 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
163187 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
163059 .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } },
163188163060 .{ .type = .f128, .kind = .mem },
163189163061 .unused,
163190163062 .unused,
......@@ -164816,7 +164688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164816164688 .extra_temps = .{
164817164689 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164818164690 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164819 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164691 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164820164692 .unused,
164821164693 .unused,
164822164694 .unused,
......@@ -164848,7 +164720,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164848164720 .extra_temps = .{
164849164721 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164850164722 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164851 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164723 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164852164724 .unused,
164853164725 .unused,
164854164726 .unused,
......@@ -164880,7 +164752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164880164752 .extra_temps = .{
164881164753 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164882164754 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164883 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164755 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164884164756 .unused,
164885164757 .unused,
164886164758 .unused,
......@@ -164913,7 +164785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164913164785 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164914164786 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164915164787 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164916 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164788 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164917164789 .{ .type = .f128, .kind = .mem },
164918164790 .unused,
164919164791 .unused,
......@@ -164947,7 +164819,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164947164819 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164948164820 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164949164821 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164950 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164822 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164951164823 .{ .type = .f128, .kind = .mem },
164952164824 .unused,
164953164825 .unused,
......@@ -164981,7 +164853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
164981164853 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
164982164854 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
164983164855 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
164984 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
164856 .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } },
164985164857 .{ .type = .f128, .kind = .mem },
164986164858 .unused,
164987164859 .unused,
......@@ -172785,7 +172657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172785172657 },
172786172658 .call_frame = .{ .alignment = .@"16" },
172787172659 .extra_temps = .{
172788 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172660 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172789172661 .unused,
172790172662 .unused,
172791172663 .unused,
......@@ -172818,7 +172690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172818172690 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172819172691 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172820172692 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172821 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172693 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172822172694 .unused,
172823172695 .unused,
172824172696 .unused,
......@@ -172852,7 +172724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172852172724 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172853172725 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172854172726 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172855 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172727 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172856172728 .unused,
172857172729 .unused,
172858172730 .unused,
......@@ -172889,7 +172761,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172889172761 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172890172762 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172891172763 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172892 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172764 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172893172765 .unused,
172894172766 .unused,
172895172767 .unused,
......@@ -172926,7 +172798,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172926172798 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172927172799 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172928172800 .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172929 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172801 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172930172802 .unused,
172931172803 .unused,
172932172804 .unused,
......@@ -172963,7 +172835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
172963172835 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172964172836 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
172965172837 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
172966 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172838 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
172967172839 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
172968172840 .unused,
172969172841 .unused,
......@@ -173000,7 +172872,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173000172872 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173001172873 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
173002172874 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
173003 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172875 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
173004172876 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173005172877 .unused,
173006172878 .unused,
......@@ -173037,7 +172909,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173037172909 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173038172910 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } },
173039172911 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } },
173040 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
172912 .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } },
173041172913 .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } },
173042172914 .unused,
173043172915 .unused,
......@@ -182636,15 +182508,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int {
182636182508 .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() },
182637182509 .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() },
182638182510 .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() },
182639 .c_char => .{ .signedness = cg.target.cCharSignedness(), .bits = cg.target.cTypeBitSize(.char) },
182640 .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) },
182641 .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) },
182642 .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) },
182643 .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) },
182644 .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) },
182645 .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) },
182646 .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) },
182647 .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) },
182511 .c_char => .{ .signedness = cg.target.cCharSignedness().?, .bits = cg.target.cTypeBitSize(.char).? },
182512 .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short).? },
182513 .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short).? },
182514 .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int).? },
182515 .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int).? },
182516 .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long).? },
182517 .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long).? },
182518 .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong).? },
182519 .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong).? },
182648182520 .f16, .f32, .f64, .f80, .f128, .c_longdouble => null,
182649182521 .anyopaque,
182650182522 .void,
src/codegen/x86_64/abi.zig+38-15
......@@ -133,7 +133,7 @@ pub fn classifyWindows(init_ty: Type, zcu: *Zcu, target: *const std.Target, ctx:
133133 .float => switch (ty.floatBits(target)) {
134134 16, 32, 64 => .sse,
135135 80 => .memory,
136 128 => if (ctx == .arg) .memory else .sse,
136 128 => .win_i128,
137137 else => unreachable,
138138 },
139139 .vector => {
......@@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
238238 };
239239 const unaligned_size = elem_ty.abiSize(zcu) * len;
240240 if (unaligned_size <= 4) return Class.one_integer;
241 if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and
242 elem_ty.isRuntimeFloat()) return Class.stack; // what
241 if (unaligned_size == 8 * 1 * 1 and len == 1) {
242 if (ctx == .arg and elem_ty.isRuntimeFloat()) return Class.stack; // what?
243 if (ctx != .other and !elem_ty.isRuntimeFloat() and target.os.tag == .freebsd) return Class.one_integer; // who?
244 }
243245 if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none };
244246 if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none };
245247 if (!target.cpu.has(.x86, .avx)) {
246248 if (ctx == .ret) switch (unaligned_size) {
247249 else => {},
248250 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{
249 .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how
250 } else Class.len_integers, // why
251 .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how?
252 } else Class.len_integers, // why?
251253 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none },
252254 };
253255 return Class.stack;
......@@ -356,11 +358,10 @@ fn classifySystemVStruct(
356358 while (field_it.next()) |field_index| {
357359 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
358360 const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index);
359 byte_offset = std.mem.alignForward(
360 u64,
361 byte_offset,
362 field_align.toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?,
363 );
361 byte_offset = switch (field_align) {
362 .none => field_ty.abiAlignment(zcu),
363 else => field_align,
364 }.forward(byte_offset);
364365 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
365366 switch (field_loaded_struct.layout) {
366367 .auto => unreachable,
......@@ -379,6 +380,9 @@ fn classifySystemVStruct(
379380 },
380381 .@"packed" => {},
381382 }
383 } else if (field_ty.zigTypeTag(zcu) == .array) {
384 byte_offset = classifySystemVArray(result, byte_offset, field_ty, zcu, target);
385 continue;
382386 }
383387 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);
384388 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
......@@ -386,11 +390,7 @@ fn classifySystemVStruct(
386390 byte_offset += field_ty.abiSize(zcu);
387391 }
388392 const final_byte_offset = starting_byte_offset + loaded_struct.size;
389 std.debug.assert(final_byte_offset == std.mem.alignForward(
390 u64,
391 byte_offset,
392 loaded_struct.alignment.toByteUnits().?,
393 ));
393 std.debug.assert(final_byte_offset == loaded_struct.alignment.forward(byte_offset));
394394 return final_byte_offset;
395395}
396396
......@@ -422,6 +422,9 @@ fn classifySystemVUnion(
422422 },
423423 .@"packed" => {},
424424 }
425 } else if (field_ty.zigTypeTag(zcu) == .array) {
426 _ = classifySystemVArray(result, starting_byte_offset, field_ty, zcu, target);
427 continue;
425428 }
426429 const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none);
427430 for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
......@@ -430,6 +433,26 @@ fn classifySystemVUnion(
430433 return starting_byte_offset + loaded_union.size;
431434}
432435
436fn classifySystemVArray(
437 result: *[8]Class,
438 starting_byte_offset: u64,
439 array_ty: Type,
440 zcu: *Zcu,
441 target: *const std.Target,
442) u64 {
443 const field_classes = std.mem.sliceTo(&classifySystemV(array_ty.childType(zcu), zcu, target, .other), .none);
444 var byte_offset = starting_byte_offset;
445 const elem_size = array_ty.childType(zcu).abiSize(zcu);
446 for (0..@intCast(array_ty.arrayLen(zcu))) |_| {
447 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
448 result_class.* = result_class.combineSystemV(field_class);
449 byte_offset += elem_size;
450 }
451 const final_byte_offset = starting_byte_offset + array_ty.abiSize(zcu);
452 assert(final_byte_offset == byte_offset);
453 return final_byte_offset;
454}
455
433456pub const zigcc = struct {
434457 pub const stack_align: ?InternPool.Alignment = null;
435458 pub const return_in_regs = true;
src/libs/mingw/Preprocessor.zig+2-2
......@@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void {
9191
9292fn defineBuiltins(pp: *Preprocessor) !void {
9393 var buf: [5]u8 = undefined;
94 var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.longdouble)}) catch unreachable;
94 var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.longdouble).?}) catch unreachable;
9595 try pp.defineBuiltinValue("__SIZEOF_LONG_DOUBLE__", val, .pp_num);
96 val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.double)}) catch unreachable;
96 val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.double).?}) catch unreachable;
9797 try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num);
9898
9999 if (pp.target.abi.isGnu()) {
src/link.zig+2-2
......@@ -1238,7 +1238,7 @@ pub const File = struct {
12381238 }
12391239
12401240 switch (base.tag) {
1241 inline .elf2, .coff2, .wasm => |tag| {
1241 inline .elf2, .coff2, .wasm, .c => |tag| {
12421242 dev.check(tag.devFeature());
12431243 try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
12441244 },
......@@ -2127,7 +2127,7 @@ pub fn resolveInputs(
21272127 continue;
21282128 },
21292129 }
2130 @compileError("unreachable");
2130 comptime unreachable;
21312131 }
21322132
21332133 if (failed_libs.items.len > 0) {
src/link/C.zig+25-24
......@@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index),
4343/// one array.
4444align_dependency_masks: std.ArrayList(u64),
4545
46/// Emitted at the top of the file. This can be cached since it only depends on the target.
47header: String,
4648/// All NAVs, regardless of whether they are functions or simple constants, are put in this map.
4749navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl),
4850/// All UAVs which may be referenced are in this map. The UAV alignment is not included in the
......@@ -404,9 +406,8 @@ pub fn createEmpty(
404406 emit: Path,
405407 options: link.File.OpenOptions,
406408) !*C {
409 assert(comp.root_mod.resolved_target.result.ofmt == .c);
407410 const io = comp.io;
408 const target = &comp.root_mod.resolved_target.result;
409 assert(target.ofmt == .c);
410411 const optimize_mode = comp.root_mod.optimize_mode;
411412 const use_lld = build_options.have_llvm and comp.config.use_lld;
412413 const use_llvm = comp.config.use_llvm;
......@@ -422,9 +423,8 @@ pub fn createEmpty(
422423 });
423424 errdefer file.close(io);
424425
425 const c_file = try arena.create(C);
426
427 c_file.* = .{
426 const c = try arena.create(C);
427 c.* = .{
428428 .base = .{
429429 .tag = .c,
430430 .comp = comp,
......@@ -439,6 +439,7 @@ pub fn createEmpty(
439439 .string_bytes = .empty,
440440 .type_dependencies = .empty,
441441 .align_dependency_masks = .empty,
442 .header = .empty,
442443 .navs = .empty,
443444 .uavs = .empty,
444445 .type_pool = .empty,
......@@ -447,8 +448,7 @@ pub fn createEmpty(
447448 .exported_navs = .empty,
448449 .exported_uavs = .empty,
449450 };
450
451 return c_file;
451 return c;
452452}
453453
454454pub fn deinit(c: *C) void {
......@@ -469,6 +469,21 @@ pub fn deinit(c: *C) void {
469469 c.exported_uavs.deinit(gpa);
470470}
471471
472pub fn prelink(c: *C, prog_node: std.Progress.Node) !void {
473 const comp = c.base.comp;
474
475 const sub_prog_node = prog_node.start("Generate Header", 0);
476 defer sub_prog_node.end();
477
478 var header_aw: std.Io.Writer.Allocating = .init(comp.gpa);
479 defer header_aw.deinit();
480 codegen.genHeader(comp.zcu.?, &header_aw.writer) catch |err| switch (err) {
481 error.WriteFailed => return error.OutOfMemory,
482 else => |e| return e,
483 };
484 c.header = try c.addString(&.{header_aw.written()});
485}
486
472487pub fn updateContainerType(
473488 c: *C,
474489 pt: Zcu.PerThread,
......@@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
727742 const io = comp.io;
728743 const zcu = c.base.comp.zcu.?;
729744 const ip = &zcu.intern_pool;
730 const target = zcu.getTarget();
731745 const active = zcu.activate(tid);
732746 defer active.deactivate();
733747 const pt = active.pt;
......@@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
943957 // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin
944958 // to build the output buffer. Our strategy is to emit the C source in this order:
945959 //
946 // * ABI defines and `#include "zig.h"`
960 // * Header
947961 // * Big-int type definitions
948962 // * Other CType definitions (traversing the dependency graph to sort topologically)
949963 // * Global assembly
......@@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
968982
969983 // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers!
970984
971 try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"`
985 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + // Header
972986 1 + // Big-int type definitions
973987 need_types.count() + // `RenderedType.fwd_decl` (worst-case)
974988 need_types.count() + // `RenderedType.definition`
......@@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
984998 need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "<definition body>")
985999 need_navs.count() * 2); // NAV definitions ("static ", "<definition body>")
9861000
987 // ABI defines and `#include "zig.h"`
988 switch (target.abi) {
989 .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"),
990 else => {},
991 }
992 f.appendBufAssumeCapacity(try std.fmt.allocPrint(
993 arena,
994 "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n",
995 .{target.cMaxIntAlignment()},
996 ));
997 f.appendBufAssumeCapacity(
998 \\#include "zig.h"
999 \\
1000 );
1001 f.appendBufAssumeCapacity(c.header.get(c));
10011002
10021003 // Big-int type definitions
10031004 var bigint_aw: std.Io.Writer.Allocating = .init(gpa);
src/link/Dwarf.zig+1-2
......@@ -4151,8 +4151,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
41514151 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
41524152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
41534153 .x86_64_vectorcall => .LLVM_vectorcall,
4154 .x86_sysv => .normal,
4155 .x86_win => .normal,
4154 .x86_sysv, .x86_win, .x86_mingw => .normal,
41564155 .x86_stdcall => .BORLAND_stdcall,
41574156 .x86_fastcall => .BORLAND_msfastcall,
41584157 .x86_thiscall => .BORLAND_thiscall,
src/main.zig+10-4
......@@ -3835,11 +3835,17 @@ fn buildOutputType(
38353835
38363836 var prev_has_cflags = false;
38373837 var prev_has_rcflags = false;
3838 if (dirs.zig_lib.path) |zig_lib_path| {
3839 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });
3840 prev_has_cflags = true;
3838 {
3839 if (dirs.zig_lib.path) |zig_lib_path| {
3840 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });
3841 prev_has_cflags = true;
3842 }
3843 const emit_ext: Compilation.FileExt = .c;
3844 const need_lang = if (comp.emit_bin) |comp_emit_bin| Compilation.classifyFileExt(comp_emit_bin) != emit_ext else true;
3845 if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", emit_ext.toLang() });
3846 try test_exec_args.append(arena, null);
3847 if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", "none" });
38413848 }
3842 try test_exec_args.append(arena, null);
38433849 for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| {
38443850 for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| {
38453851 const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len;
src/target.zig+3-3
......@@ -876,18 +876,18 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 {
876876 32 => "f",
877877 64 => "",
878878 80 => "x", // Non-standard
879 128 => "q", // Non-standard (mimics convention in GCC libquadmath)
879 128 => "f128",
880880 else => unreachable,
881881 };
882882}
883883
884pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 {
884pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 {
885885 return switch (float_bits) {
886886 16 => "h",
887887 32 => "s",
888888 64 => "d",
889889 80 => "x",
890 128 => "t",
890 128 => if (target.cpu.arch.isPowerPC()) "k" else "t",
891891 else => unreachable,
892892 };
893893}
stage1/zig.h+3079-991
......@@ -166,6 +166,12 @@
166166#endif
167167#define zig_expand_has_builtin(b) zig_has_builtin(b)
168168
169#if defined(__has_feature)
170#define zig_has_feature(feature) __has_feature(feature)
171#else
172#define zig_has_feature(feature) 0
173#endif
174
169175#if defined(__has_attribute)
170176#define zig_has_attribute(attribute) __has_attribute(attribute)
171177#else
......@@ -175,9 +181,9 @@
175181#if __STDC_VERSION__ >= 201112L
176182#define zig_static_assert(cond, msg) _Static_assert(cond, msg)
177183#elif zig_has_attribute(unused)
178#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused))
184#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused))
179185#else
180#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)]
186#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1]
181187#endif
182188
183189#if __STDC_VERSION__ >= 202311L
......@@ -193,10 +199,8 @@
193199#endif
194200
195201#if defined(zig_msvc)
196#define zig_const_arr
197202#define zig_callconv(c) __##c
198203#else
199#define zig_const_arr static const
200204#define zig_callconv(c) __attribute__((c))
201205#endif
202206
......@@ -267,12 +271,20 @@
267271
268272#if __STDC_VERSION__ >= 202311L
269273#define zig_align(alignment) alignas(alignment)
270#elif __STDC_VERSION__ >= 201112L
274#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas)
271275#define zig_align(alignment) _Alignas(alignment)
272276#else
273277#define zig_align(alignment) zig_under_align(alignment)
274278#endif
275279
280#if __STDC_VERSION__ >= 202311L
281#define zig_alignOf(Type) alignof(Type)
282#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof)
283#define zig_alignOf(Type) _Alignof(Type)
284#else
285#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type))
286#endif
287
276288#if zig_has_attribute(aligned) || defined(zig_tinyc)
277289#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
278290#elif defined(zig_msvc)
......@@ -350,11 +362,9 @@
350362#define zig_export(symbol, name) __attribute__((alias(symbol)))
351363#else
352364#define zig_export(symbol, name) ; \
353 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
365 __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol))
354366#endif
355367
356#define zig_mangled_tentative zig_mangled
357#define zig_mangled_final zig_mangled
358368#if defined(zig_msvc)
359369#define zig_mangled(mangled, unmangled) ; \
360370 zig_export(#mangled, unmangled)
......@@ -364,7 +374,7 @@
364374#else /* zig_msvc */
365375#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
366376#define zig_mangled_export(mangled, unmangled, symbol) \
367 zig_mangled_final(mangled, unmangled) \
377 zig_mangled(mangled, unmangled) \
368378 zig_export(symbol, unmangled)
369379#endif /* zig_msvc */
370380
......@@ -550,6 +560,9 @@
550560#define zig_noreturn
551561#endif
552562
563#define zig_has_always 1
564#define zig_has_never 0
565
553566#define zig_compiler_rt_abbrev_uint32_t si
554567#define zig_compiler_rt_abbrev_int32_t si
555568#define zig_compiler_rt_abbrev_uint64_t di
......@@ -560,7 +573,11 @@
560573#define zig_compiler_rt_abbrev_zig_f32 sf
561574#define zig_compiler_rt_abbrev_zig_f64 df
562575#define zig_compiler_rt_abbrev_zig_f80 xf
576#ifdef zig_powerpc
577#define zig_compiler_rt_abbrev_zig_f128 kf
578#else
563579#define zig_compiler_rt_abbrev_zig_f128 tf
580#endif
564581
565582zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
566583zig_extern void *memset (void *, int, size_t);
......@@ -645,16 +662,6 @@ typedef signed long long int16_t;
645662#define INT16_MAX ( INT16_C(0x7FFF))
646663#define UINT16_MAX ( INT16_C(0xFFFF))
647664
648#if defined(zig_ez80)
649typedef unsigned int uint24_t;
650typedef signed int int24_t;
651#define INT24_C(c) c
652#define UINT24_C(c) c##U
653#endif
654#define INT24_MIN (~INT24_C(0x7FFF))
655#define INT24_MAX ( INT24_C(0x7FFF))
656#define UINT24_MAX ( INT24_C(0xFFFF))
657
658665#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
659666typedef unsigned char uint32_t;
660667typedef signed char int32_t;
......@@ -685,17 +692,6 @@ typedef signed long long int32_t;
685692#define INT32_MAX ( INT32_C(0x7FFFFFFF))
686693#define UINT32_MAX ( INT32_C(0xFFFFFFFF))
687694
688#if defined(zig_ez80)
689typedef unsigned __int48 uint48_t;
690typedef signed __int48 int48_t;
691#define INT48_C(c) c
692/* no suffix */
693#define UINT48_C(c) ((uint48_t)(c))
694#endif
695#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
696#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
697#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
698
699695#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
700696typedef unsigned char uint64_t;
701697typedef signed char int64_t;
......@@ -726,6 +722,27 @@ typedef signed long long int64_t;
726722#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
727723#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))
728724
725#if defined(zig_ez80)
726
727typedef unsigned int uint24_t;
728typedef signed int int24_t;
729#define INT24_C(c) c
730#define UINT24_C(c) c##U
731#define INT24_MIN (~INT24_C(0x7FFF))
732#define INT24_MAX ( INT24_C(0x7FFF))
733#define UINT24_MAX ( INT24_C(0xFFFF))
734
735typedef unsigned __int48 uint48_t;
736typedef signed __int48 int48_t;
737#define INT48_C(c) c
738/* no suffix */
739#define UINT48_C(c) ((uint48_t)(c))
740#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF))
741#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF))
742#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF))
743
744#endif
745
729746typedef size_t uintptr_t;
730747typedef ptrdiff_t intptr_t;
731748
......@@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t;
739756#define zig_maxInt_i16 INT16_MAX
740757#define zig_minInt_u16 UINT16_C(0)
741758#define zig_maxInt_u16 UINT16_MAX
742#define zig_minInt_i24 INT24_MIN
743#define zig_maxInt_i24 INT24_MAX
744#define zig_minInt_u24 UINT24_C(0)
745#define zig_maxInt_u24 UINT24_MAX
746759#define zig_minInt_i32 INT32_MIN
747760#define zig_maxInt_i32 INT32_MAX
748761#define zig_minInt_u32 UINT32_C(0)
749762#define zig_maxInt_u32 UINT32_MAX
750#define zig_minInt_i48 INT48_MIN
751#define zig_maxInt_i48 INT48_MAX
752#define zig_minInt_u48 UINT48_C(0)
753#define zig_maxInt_u48 UINT48_MAX
754763#define zig_minInt_i64 INT64_MIN
755764#define zig_maxInt_i64 INT64_MAX
756765#define zig_minInt_u64 UINT64_C(0)
757766#define zig_maxInt_u64 UINT64_MAX
758767
768// zig_promoted_T implements C integral promotions except with signedness preserved, which
769// allows wrapping operations to avoid the ub that would be caused by the normal promotion.
770
771#if INT8_MAX <= INT_MAX
772typedef unsigned int zig_promoted_i8;
773#elif INT8_MAX <= LONG_MAX
774typedef unsigned long zig_promoted_i8;
775#elif INT8_MAX <= LLONG_MAX
776typedef unsigned long long zig_promoted_i8;
777#else
778typedef int8_t zig_promoted_i8;
779#endif
780#if UINT8_MAX <= UINT_MAX
781typedef unsigned int zig_promoted_u8;
782#elif UINT8_MAX <= ULONG_MAX
783typedef unsigned long zig_promoted_u8;
784#elif UINT8_MAX <= ULLONG_MAX
785typedef unsigned long long zig_promoted_u8;
786#else
787typedef uint8_t zig_promoted_u8;
788#endif
789
790#if INT16_MAX <= INT_MAX
791typedef unsigned int zig_promoted_i16;
792#elif INT16_MAX <= LONG_MAX
793typedef unsigned long zig_promoted_i16;
794#elif INT16_MAX <= LLONG_MAX
795typedef unsigned long long zig_promoted_i16;
796#else
797typedef int16_t zig_promoted_i16;
798#endif
799#if UINT16_MAX <= UINT_MAX
800typedef unsigned int zig_promoted_u16;
801#elif UINT16_MAX <= ULONG_MAX
802typedef unsigned long zig_promoted_u16;
803#elif UINT16_MAX <= ULLONG_MAX
804typedef unsigned long long zig_promoted_u16;
805#else
806typedef uint16_t zig_promoted_u16;
807#endif
808
809#if INT32_MAX <= INT_MAX
810typedef unsigned int zig_promoted_i32;
811#elif INT32_MAX <= LONG_MAX
812typedef unsigned long zig_promoted_i32;
813#elif INT32_MAX <= LLONG_MAX
814typedef unsigned long long zig_promoted_i32;
815#else
816typedef int32_t zig_promoted_i32;
817#endif
818#if UINT32_MAX <= UINT_MAX
819typedef unsigned int zig_promoted_u32;
820#elif UINT32_MAX <= ULONG_MAX
821typedef unsigned long zig_promoted_u32;
822#elif UINT32_MAX <= ULLONG_MAX
823typedef unsigned long long zig_promoted_u32;
824#else
825typedef uint32_t zig_promoted_u32;
826#endif
827
828#if INT64_MAX <= INT_MAX
829typedef unsigned int zig_promoted_i64;
830#elif INT64_MAX <= LONG_MAX
831typedef unsigned long zig_promoted_i64;
832#elif INT64_MAX <= LLONG_MAX
833typedef unsigned long long zig_promoted_i64;
834#else
835typedef int64_t zig_promoted_i64;
836#endif
837#if UINT64_MAX <= UINT_MAX
838typedef unsigned int zig_promoted_u64;
839#elif UINT64_MAX <= ULONG_MAX
840typedef unsigned long zig_promoted_u64;
841#elif UINT64_MAX <= ULLONG_MAX
842typedef unsigned long long zig_promoted_u64;
843#else
844typedef uint64_t zig_promoted_u64;
845#endif
846
847#ifdef zig_ez80
848
849#define zig_minInt_i24 INT24_MIN
850#define zig_maxInt_i24 INT24_MAX
851#define zig_minInt_u24 UINT24_C(0)
852#define zig_maxInt_u24 UINT24_MAX
853#define zig_minInt_i48 INT48_MIN
854#define zig_maxInt_i48 INT48_MAX
855#define zig_minInt_u48 UINT48_C(0)
856#define zig_maxInt_u48 UINT48_MAX
857
858#if INT24_MAX <= INT_MAX
859typedef unsigned int zig_promoted_i24;
860#elif INT24_MAX <= LONG_MAX
861typedef unsigned long zig_promoted_i24;
862#elif INT24_MAX <= LLONG_MAX
863typedef unsigned long long zig_promoted_i24;
864#else
865typedef int24_t zig_promoted_i24;
866#endif
867#if UINT24_MAX <= UINT_MAX
868typedef unsigned int zig_promoted_u24;
869#elif UINT24_MAX <= ULONG_MAX
870typedef unsigned long zig_promoted_u24;
871#elif UINT24_MAX <= ULLONG_MAX
872typedef unsigned long long zig_promoted_u24;
873#else
874typedef uint24_t zig_promoted_u24;
875#endif
876
877#if INT48_MAX <= INT_MAX
878typedef unsigned int zig_promoted_i48;
879#elif INT48_MAX <= LONG_MAX
880typedef unsigned long zig_promoted_i48;
881#elif INT48_MAX <= LLONG_MAX
882typedef unsigned long long zig_promoted_i48;
883#else
884typedef int48_t zig_promoted_i48;
885#endif
886#if UINT48_MAX <= UINT_MAX
887typedef unsigned int zig_promoted_u48;
888#elif UINT48_MAX <= ULONG_MAX
889typedef unsigned long zig_promoted_u48;
890#elif UINT48_MAX <= ULLONG_MAX
891typedef unsigned long long zig_promoted_u48;
892#else
893typedef uint48_t zig_promoted_u48;
894#endif
895
896#endif
897
759898#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
760899#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
761900#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
......@@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t;
770909 zig_operator(Type, Type, operation, operator)
771910#define zig_shift_operator(Type, operation, operator) \
772911 zig_operator(Type, uint8_t, operation, operator)
773#define zig_int_helpers(w, PromotedUnsigned) \
912
913#define zig_int_casts_common(bw, sw) \
914 static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \
915 return arg; \
916 } \
917\
918 static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \
919 return (uint##bw##_t)arg; \
920 } \
921\
922 static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \
923 return arg; \
924 } \
925\
926 static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \
927 return arg; \
928 } \
929\
930 static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \
931 return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \
932 } \
933\
934 static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \
935 return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \
936 ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \
937 }
938#define zig_int_operators(w) \
774939 zig_basic_operator(uint##w##_t, and_u##w, &) \
775940 zig_basic_operator( int##w##_t, and_i##w, &) \
776941 zig_basic_operator(uint##w##_t, or_u##w, |) \
......@@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t;
786951 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
787952 } \
788953\
789 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
790 return val ^ zig_maxInt_u(w, bits); \
954 static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \
955 return arg ^ zig_maxInt_u(w, bits); \
791956 } \
792957\
793 static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \
958 static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \
794959 (void)bits; \
795 return ~val; \
960 return ~arg; \
796961 } \
797962\
798 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
799 return val & zig_maxInt_u(w, bits); \
963 zig_basic_operator(uint##w##_t, divFloor_u##w, /) \
964\
965 static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \
966 return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \
800967 } \
801968\
802 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
803 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
804 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
969 static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
970 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
805971 } \
806972\
807 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \
808 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \
973 static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \
974 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
975 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
809976 } \
810977\
811 zig_basic_operator(uint##w##_t, div_floor_u##w, /) \
978 zig_basic_operator(uint##w##_t, mod_u##w, %) \
979 zig_int_casts_common(w, w) \
812980\
813 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
814 return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \
981 static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
982 return zig_u##w##_truncate_u##w(arg, bits); \
815983 } \
816984\
817 static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
818 return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \
985 static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
986 return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \
819987 } \
820988\
821 static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \
822 return lhs / rhs + (lhs % rhs != INT##w##_C(0) \
823 ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \
989 static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \
990 return zig_i##w##_truncate_i##w(arg, bits); \
824991 } \
825992\
826 zig_basic_operator(uint##w##_t, mod_u##w, %) \
993 static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \
994 return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \
995 } \
827996\
828997 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
829998 int##w##_t rem = lhs % rhs; \
......@@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t;
8311000 } \
8321001\
8331002 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
834 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
1003 return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \
8351004 } \
8361005\
8371006 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
838 return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \
1007 return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \
8391008 } \
8401009\
8411010 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
842 return zig_wrap_u##w(lhs + rhs, bits); \
1011 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \
8431012 } \
8441013\
8451014 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
846 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
1015 return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \
8471016 } \
8481017\
8491018 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
850 return zig_wrap_u##w(lhs - rhs, bits); \
1019 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \
8511020 } \
8521021\
8531022 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
854 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
1023 return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \
8551024 } \
8561025\
8571026 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
858 return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \
1027 return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \
8591028 } \
8601029\
8611030 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
862 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
1031 return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \
1032 } \
1033\
1034 static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \
1035 int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \
1036 return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \
1037 } \
1038\
1039 static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1040 return lhs < rhs ? lhs : rhs; \
1041 } \
1042\
1043 static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \
1044 return lhs < rhs ? lhs : rhs; \
1045 } \
1046\
1047 static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \
1048 return lhs >= rhs ? lhs : rhs; \
1049 } \
1050\
1051 static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \
1052 return lhs >= rhs ? lhs : rhs; \
8631053 }
864#if UINT8_MAX <= UINT_MAX
865zig_int_helpers(8, unsigned int)
866#elif UINT8_MAX <= ULONG_MAX
867zig_int_helpers(8, unsigned long)
868#elif UINT8_MAX <= ULLONG_MAX
869zig_int_helpers(8, unsigned long long)
870#else
871zig_int_helpers(8, uint8_t)
872#endif
873#if UINT16_MAX <= UINT_MAX
874zig_int_helpers(16, unsigned int)
875#elif UINT16_MAX <= ULONG_MAX
876zig_int_helpers(16, unsigned long)
877#elif UINT16_MAX <= ULLONG_MAX
878zig_int_helpers(16, unsigned long long)
879#else
880zig_int_helpers(16, uint16_t)
881#endif
882#if defined(zig_ez80)
883#if UINT24_MAX <= UINT_MAX
884zig_int_helpers(24, unsigned int)
885#elif UINT24_MAX <= ULONG_MAX
886zig_int_helpers(24, unsigned long)
887#elif UINT24_MAX <= ULLONG_MAX
888zig_int_helpers(24, unsigned long long)
889#else
890zig_int_helpers(24, uint24_t)
891#endif
892#endif
893#if UINT32_MAX <= UINT_MAX
894zig_int_helpers(32, unsigned int)
895#elif UINT32_MAX <= ULONG_MAX
896zig_int_helpers(32, unsigned long)
897#elif UINT32_MAX <= ULLONG_MAX
898zig_int_helpers(32, unsigned long long)
899#else
900zig_int_helpers(32, uint32_t)
901#endif
902#if defined(zig_ez80)
903#if UINT24_MAX <= UINT_MAX
904zig_int_helpers(48, unsigned int)
905#elif UINT24_MAX <= ULONG_MAX
906zig_int_helpers(48, unsigned long)
907#elif UINT24_MAX <= ULLONG_MAX
908zig_int_helpers(48, unsigned long long)
909#else
910zig_int_helpers(48, uint48_t)
911#endif
912#endif
913#if UINT64_MAX <= UINT_MAX
914zig_int_helpers(64, unsigned int)
915#elif UINT64_MAX <= ULONG_MAX
916zig_int_helpers(64, unsigned long)
917#elif UINT64_MAX <= ULLONG_MAX
918zig_int_helpers(64, unsigned long long)
919#else
920zig_int_helpers(64, uint64_t)
1054zig_int_operators(8)
1055zig_int_operators(16)
1056zig_int_operators(32)
1057zig_int_operators(64)
1058#ifdef zig_ez80
1059zig_int_operators(24)
1060zig_int_operators(48)
1061#endif
1062
1063#define zig_int_casts(bw, sw) \
1064 static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \
1065 return (uint##sw##_t)arg; \
1066 } \
1067\
1068 static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \
1069 return (uint##sw##_t)arg; \
1070 } \
1071\
1072 static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \
1073 return (int##sw##_t)arg; \
1074 } \
1075\
1076 static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \
1077 return (int##sw##_t)arg; \
1078 } \
1079\
1080 zig_int_casts_common(bw, sw)
1081zig_int_casts(16, 8)
1082zig_int_casts(32, 8)
1083zig_int_casts(64, 8)
1084zig_int_casts(32, 16)
1085zig_int_casts(64, 16)
1086zig_int_casts(64, 32)
1087#ifdef zig_ez80
1088zig_int_casts(32, 24)
1089zig_int_casts(48, 24)
1090zig_int_casts(64, 24)
1091zig_int_casts(64, 48)
9211092#endif
9221093
9231094static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
9241095#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9251096 uint32_t full_res;
9261097 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
927 *res = zig_wrap_u32(full_res, bits);
1098 *res = zig_u32_truncate_u32(full_res, bits);
9281099 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
9291100#else
9301101 *res = zig_addw_u32(lhs, rhs, bits);
......@@ -936,19 +1107,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
9361107#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9371108 int32_t full_res;
9381109 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1110 *res = zig_i32_truncate_i32(full_res, bits);
1111 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9391112#else
940 int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs);
941 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1113 *res = zig_addw_i32(lhs, rhs, bits);
1114 return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0);
9421115#endif
943 *res = zig_wrap_i32(full_res, bits);
944 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
9451116}
9461117
9471118static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
9481119#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9491120 uint64_t full_res;
9501121 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
951 *res = zig_wrap_u64(full_res, bits);
1122 *res = zig_u64_truncate_u64(full_res, bits);
9521123 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
9531124#else
9541125 *res = zig_addw_u64(lhs, rhs, bits);
......@@ -960,24 +1131,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
9601131#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9611132 int64_t full_res;
9621133 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1134 *res = zig_i64_truncate_i64(full_res, bits);
1135 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9631136#else
964 int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs);
965 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
1137 *res = zig_addw_i64(lhs, rhs, bits);
1138 return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0);
9661139#endif
967 *res = zig_wrap_i64(full_res, bits);
968 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
9691140}
9701141
9711142static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
9721143#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9731144 uint8_t full_res;
9741145 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
975 *res = zig_wrap_u8(full_res, bits);
1146 *res = zig_u8_truncate_u8(full_res, bits);
9761147 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
9771148#else
9781149 uint32_t full_res;
9791150 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
980 *res = (uint8_t)full_res;
1151 *res = zig_u8_intCast_u32(full_res);
9811152 return overflow;
9821153#endif
9831154}
......@@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
9861157#if zig_has_builtin(add_overflow) || defined(zig_gcc)
9871158 int8_t full_res;
9881159 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
989 *res = zig_wrap_i8(full_res, bits);
1160 *res = zig_i8_truncate_i8(full_res, bits);
9901161 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
9911162#else
9921163 int32_t full_res;
9931164 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
994 *res = (int8_t)full_res;
1165 *res = zig_i8_intCast_i32(full_res);
9951166 return overflow;
9961167#endif
9971168}
......@@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
10001171#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10011172 uint16_t full_res;
10021173 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1003 *res = zig_wrap_u16(full_res, bits);
1174 *res = zig_u16_truncate_u16(full_res, bits);
10041175 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
10051176#else
10061177 uint32_t full_res;
10071178 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1008 *res = (uint16_t)full_res;
1179 *res = zig_u16_intCast_u32(full_res);
10091180 return overflow;
10101181#endif
10111182}
......@@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
10141185#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10151186 int16_t full_res;
10161187 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1017 *res = zig_wrap_i16(full_res, bits);
1188 *res = zig_i16_truncate_i16(full_res, bits);
10181189 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
10191190#else
10201191 int32_t full_res;
10211192 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1022 *res = (int16_t)full_res;
1193 *res = zig_i16_intCast_i32(full_res);
10231194 return overflow;
10241195#endif
10251196}
10261197
10271198#if defined(zig_ez80)
1199
10281200static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
10291201#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10301202 uint24_t full_res;
10311203 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1032 *res = zig_wrap_u24(full_res, bits);
1204 *res = zig_u24_truncate_u24(full_res, bits);
10331205 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
10341206#else
10351207 uint32_t full_res;
10361208 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
1037 *res = (uint24_t)full_res;
1209 *res = zig_u24_intCast_u32(full_res);
10381210 return overflow;
10391211#endif
10401212}
......@@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
10431215#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10441216 int24_t full_res;
10451217 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1046 *res = zig_wrap_i24(full_res, bits);
1218 *res = zig_i24_truncate_i24(full_res, bits);
10471219 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
10481220#else
10491221 int32_t full_res;
10501222 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
1051 *res = (int24_t)full_res;
1223 *res = zig_i24_intCast_i32(full_res);
10521224 return overflow;
10531225#endif
10541226}
1055#endif
10561227
1057#if defined(zig_ez80)
10581228static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
10591229#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10601230 uint48_t full_res;
10611231 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1062 *res = zig_wrap_u48(full_res, bits);
1232 *res = zig_u48_truncate_u48(full_res, bits);
10631233 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
10641234#else
10651235 uint64_t full_res;
10661236 bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits);
1067 *res = (uint48_t)full_res;
1237 *res = zig_u48_intCast_u64(full_res);
10681238 return overflow;
10691239#endif
10701240}
......@@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
10731243#if zig_has_builtin(add_overflow) || defined(zig_gcc)
10741244 int48_t full_res;
10751245 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1076 *res = zig_wrap_i48(full_res, bits);
1246 *res = zig_i48_truncate_i48(full_res, bits);
10771247 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
10781248#else
10791249 int64_t full_res;
10801250 bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits);
1081 *res = (int48_t)full_res;
1251 *res = zig_i48_intCast_i64(full_res);
10821252 return overflow;
10831253#endif
10841254}
1255
10851256#endif
10861257
10871258static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
10881259#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
10891260 uint32_t full_res;
10901261 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1091 *res = zig_wrap_u32(full_res, bits);
1262 *res = zig_u32_truncate_u32(full_res, bits);
10921263 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
10931264#else
10941265 *res = zig_subw_u32(lhs, rhs, bits);
......@@ -1100,20 +1271,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
11001271#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11011272 int32_t full_res;
11021273 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1274 *res = zig_i32_truncate_i32(full_res, bits);
1275 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11031276#else
1104 int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs);
1105 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1277 *res = zig_subw_i32(lhs, rhs, bits);
1278 return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0);
11061279#endif
1107 *res = zig_wrap_i32(full_res, bits);
1108 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
11091280}
11101281
1111
11121282static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
11131283#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11141284 uint64_t full_res;
11151285 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1116 *res = zig_wrap_u64(full_res, bits);
1286 *res = zig_u64_truncate_u64(full_res, bits);
11171287 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
11181288#else
11191289 *res = zig_subw_u64(lhs, rhs, bits);
......@@ -1125,24 +1295,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
11251295#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11261296 int64_t full_res;
11271297 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1298 *res = zig_i64_truncate_i64(full_res, bits);
1299 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11281300#else
1129 int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs);
1130 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
1301 *res = zig_subw_i64(lhs, rhs, bits);
1302 return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0);
11311303#endif
1132 *res = zig_wrap_i64(full_res, bits);
1133 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
11341304}
11351305
11361306static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
11371307#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11381308 uint8_t full_res;
11391309 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1140 *res = zig_wrap_u8(full_res, bits);
1310 *res = zig_u8_truncate_u8(full_res, bits);
11411311 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
11421312#else
11431313 uint32_t full_res;
11441314 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1145 *res = (uint8_t)full_res;
1315 *res = zig_u8_intCast_u32(full_res);
11461316 return overflow;
11471317#endif
11481318}
......@@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
11511321#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11521322 int8_t full_res;
11531323 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1154 *res = zig_wrap_i8(full_res, bits);
1324 *res = zig_i8_truncate_i8(full_res, bits);
11551325 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
11561326#else
11571327 int32_t full_res;
11581328 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1159 *res = (int8_t)full_res;
1329 *res = zig_i8_intCast_i32(full_res);
11601330 return overflow;
11611331#endif
11621332}
......@@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
11651335#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11661336 uint16_t full_res;
11671337 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1168 *res = zig_wrap_u16(full_res, bits);
1338 *res = zig_u16_truncate_u16(full_res, bits);
11691339 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
11701340#else
11711341 uint32_t full_res;
11721342 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1173 *res = (uint16_t)full_res;
1343 *res = zig_u16_intCast_u32(full_res);
11741344 return overflow;
11751345#endif
11761346}
......@@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
11791349#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11801350 int16_t full_res;
11811351 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1182 *res = zig_wrap_i16(full_res, bits);
1352 *res = zig_i16_truncate_i16(full_res, bits);
11831353 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
11841354#else
11851355 int32_t full_res;
11861356 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1187 *res = (int16_t)full_res;
1357 *res = zig_i16_intCast_i32(full_res);
11881358 return overflow;
11891359#endif
11901360}
11911361
11921362#if defined(zig_ez80)
1363
11931364static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
11941365#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
11951366 uint24_t full_res;
11961367 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1197 *res = zig_wrap_u24(full_res, bits);
1368 *res = zig_u24_truncate_u24(full_res, bits);
11981369 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
11991370#else
12001371 uint32_t full_res;
12011372 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
1202 *res = (uint24_t)full_res;
1373 *res = zig_u24_intCast_u32(full_res);
12031374 return overflow;
12041375#endif
12051376}
......@@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
12081379#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12091380 int24_t full_res;
12101381 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1211 *res = zig_wrap_i24(full_res, bits);
1382 *res = zig_i24_truncate_i24(full_res, bits);
12121383 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
12131384#else
12141385 int32_t full_res;
12151386 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
1216 *res = (int24_t)full_res;
1387 *res = zig_i24_intCast_i32(full_res);
12171388 return overflow;
12181389#endif
12191390}
1220#endif
12211391
1222#if defined(zig_ez80)
12231392static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
12241393#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12251394 uint48_t full_res;
12261395 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1227 *res = zig_wrap_u48(full_res, bits);
1396 *res = zig_u48_truncate_u48(full_res, bits);
12281397 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
12291398#else
12301399 uint64_t full_res;
12311400 bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits);
1232 *res = (uint48_t)full_res;
1401 *res = zig_u48_intCast_u64(full_res);
12331402 return overflow;
12341403#endif
12351404}
......@@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
12381407#if zig_has_builtin(sub_overflow) || defined(zig_gcc)
12391408 int48_t full_res;
12401409 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1241 *res = zig_wrap_i48(full_res, bits);
1410 *res = zig_i48_truncate_i48(full_res, bits);
12421411 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
12431412#else
12441413 int64_t full_res;
12451414 bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits);
1246 *res = (int48_t)full_res;
1415 *res = zig_i48_intCast_i64(full_res);
12471416 return overflow;
12481417#endif
12491418}
1419
12501420#endif
12511421
12521422static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
12531423#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12541424 uint32_t full_res;
12551425 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1256 *res = zig_wrap_u32(full_res, bits);
1426 *res = zig_u32_truncate_u32(full_res, bits);
12571427 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
12581428#else
12591429 *res = zig_mulw_u32(lhs, rhs, bits);
......@@ -1261,8 +1431,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
12611431#endif
12621432}
12631433
1264zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12651434static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
1435 zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
12661436#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12671437 int32_t full_res;
12681438 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
......@@ -1271,7 +1441,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
12711441 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
12721442 bool overflow = overflow_int != 0;
12731443#endif
1274 *res = zig_wrap_i32(full_res, bits);
1444 *res = zig_i32_truncate_i32(full_res, bits);
12751445 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
12761446}
12771447
......@@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
12791449#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12801450 uint64_t full_res;
12811451 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1282 *res = zig_wrap_u64(full_res, bits);
1452 *res = zig_u64_truncate_u64(full_res, bits);
12831453 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
12841454#else
12851455 *res = zig_mulw_u64(lhs, rhs, bits);
......@@ -1287,8 +1457,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
12871457#endif
12881458}
12891459
1290zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12911460static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
1461 zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
12921462#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
12931463 int64_t full_res;
12941464 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
......@@ -1297,7 +1467,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
12971467 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
12981468 bool overflow = overflow_int != 0;
12991469#endif
1300 *res = zig_wrap_i64(full_res, bits);
1470 *res = zig_i64_truncate_i64(full_res, bits);
13011471 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
13021472}
13031473
......@@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
13051475#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13061476 uint8_t full_res;
13071477 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1308 *res = zig_wrap_u8(full_res, bits);
1478 *res = zig_u8_truncate_u8(full_res, bits);
13091479 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
13101480#else
13111481 uint32_t full_res;
13121482 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1313 *res = (uint8_t)full_res;
1483 *res = zig_u8_intCast_u32(full_res);
13141484 return overflow;
13151485#endif
13161486}
......@@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
13191489#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13201490 int8_t full_res;
13211491 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1322 *res = zig_wrap_i8(full_res, bits);
1492 *res = zig_i8_truncate_i8(full_res, bits);
13231493 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
13241494#else
13251495 int32_t full_res;
13261496 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1327 *res = (int8_t)full_res;
1497 *res = zig_i8_intCast_i32(full_res);
13281498 return overflow;
13291499#endif
13301500}
......@@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
13331503#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13341504 uint16_t full_res;
13351505 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1336 *res = zig_wrap_u16(full_res, bits);
1506 *res = zig_u16_truncate_u16(full_res, bits);
13371507 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
13381508#else
13391509 uint32_t full_res;
13401510 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1341 *res = (uint16_t)full_res;
1511 *res = zig_u16_intCast_u32(full_res);
13421512 return overflow;
13431513#endif
13441514}
......@@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
13471517#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13481518 int16_t full_res;
13491519 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1350 *res = zig_wrap_i16(full_res, bits);
1520 *res = zig_i16_truncate_i16(full_res, bits);
13511521 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
13521522#else
13531523 int32_t full_res;
13541524 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1355 *res = (int16_t)full_res;
1525 *res = zig_i16_intCast_i32(full_res);
13561526 return overflow;
13571527#endif
13581528}
13591529
13601530#if defined(zig_ez80)
1531
13611532static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) {
13621533#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13631534 uint24_t full_res;
13641535 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1365 *res = zig_wrap_u24(full_res, bits);
1536 *res = zig_u24_truncate_u24(full_res, bits);
13661537 return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits);
13671538#else
13681539 uint32_t full_res;
13691540 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
1370 *res = (uint24_t)full_res;
1541 *res = zig_u24_intCast_u32(full_res);
13711542 return overflow;
13721543#endif
13731544}
......@@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t
13761547#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13771548 int24_t full_res;
13781549 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1379 *res = zig_wrap_i24(full_res, bits);
1550 *res = zig_i24_truncate_i24(full_res, bits);
13801551 return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits);
13811552#else
13821553 int32_t full_res;
13831554 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
1384 *res = (int24_t)full_res;
1555 *res = zig_i24_intCast_i32(full_res);
13851556 return overflow;
13861557#endif
13871558}
1388#endif
13891559
1390#if defined(zig_ez80)
13911560static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) {
13921561#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
13931562 uint48_t full_res;
13941563 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1395 *res = zig_wrap_u48(full_res, bits);
1564 *res = zig_u48_truncate_u48(full_res, bits);
13961565 return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits);
13971566#else
13981567 uint64_t full_res;
13991568 bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits);
1400 *res = (uint48_t)full_res;
1569 *res = zig_u48_intCast_u64(full_res);
14011570 return overflow;
14021571#endif
14031572}
......@@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14061575#if zig_has_builtin(mul_overflow) || defined(zig_gcc)
14071576 int48_t full_res;
14081577 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1409 *res = zig_wrap_i48(full_res, bits);
1578 *res = zig_i48_truncate_i48(full_res, bits);
14101579 return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits);
14111580#else
14121581 int64_t full_res;
14131582 bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits);
1414 *res = (int48_t)full_res;
1583 *res = zig_i48_intCast_i64(full_res);
14151584 return overflow;
14161585#endif
14171586}
1587
14181588#endif
14191589
1420#define zig_int_builtins(w) \
1590#define zig_shls_builtins(lw, rw) \
1591 static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1592 uint##lw##_t res; \
1593 if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1594 return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \
1595 } \
1596\
1597 static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \
1598 int##lw##_t res; \
1599 if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
1600 return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \
1601 lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \
1602 }
1603#define zig_int_sat_builtins(w) \
14211604 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
14221605 *res = zig_shlw_u##w(lhs, rhs, bits); \
14231606 return lhs > zig_maxInt_u(w, bits) >> rhs; \
......@@ -1429,18 +1612,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14291612 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
14301613 } \
14311614\
1432 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1433 uint##w##_t res; \
1434 if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \
1435 return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \
1436 } \
1437\
1438 static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1439 int##w##_t res; \
1440 if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
1441 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
1442 lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
1443 } \
1615 zig_shls_builtins(w, 8) \
1616 zig_shls_builtins(w, 16) \
1617 zig_shls_builtins(w, 32) \
1618 zig_shls_builtins(w, 64) \
14441619\
14451620 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
14461621 uint##w##_t res; \
......@@ -1474,332 +1649,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t
14741649 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
14751650 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
14761651 }
1477zig_int_builtins(8)
1478zig_int_builtins(16)
1479#if defined(zig_ez80)
1480zig_int_builtins(24)
1481#endif
1482zig_int_builtins(32)
1652zig_int_sat_builtins(8)
1653zig_int_sat_builtins(16)
1654zig_int_sat_builtins(32)
1655zig_int_sat_builtins(64)
14831656#if defined(zig_ez80)
1484zig_int_builtins(48)
1657zig_int_sat_builtins(24)
1658zig_int_sat_builtins(48)
14851659#endif
1486zig_int_builtins(64)
14871660
1488#define zig_builtin8(name, val) __builtin_##name(val)
1661#define zig_builtin8(name, arg) __builtin_##name(arg)
14891662typedef unsigned int zig_Builtin8;
14901663
1491#define zig_builtin16(name, val) __builtin_##name(val)
1664#define zig_builtin16(name, arg) __builtin_##name(arg)
14921665typedef unsigned int zig_Builtin16;
14931666
1494#if defined(zig_ez80)
1495#define zig_builtin24(name, val) __builtin_##name(val)
1496typedef unsigned int zig_Builtin24;
1497#endif
1498
14991667#if INT_MIN <= INT32_MIN
1500#define zig_builtin32(name, val) __builtin_##name(val)
1668#define zig_builtin32(name, arg) __builtin_##name(arg)
15011669typedef unsigned int zig_Builtin32;
15021670#elif LONG_MIN <= INT32_MIN
1503#define zig_builtin32(name, val) __builtin_##name##l(val)
1671#define zig_builtin32(name, arg) __builtin_##name##l(arg)
15041672typedef unsigned long zig_Builtin32;
15051673#endif
15061674
1507#if defined(zig_ez80)
1508#define zig_builtin48(name, val) __builtin_##name(val)
1509typedef unsigned long long zig_Builtin48;
1510#endif
1511
15121675#if INT_MIN <= INT64_MIN
1513#define zig_builtin64(name, val) __builtin_##name(val)
1676#define zig_builtin64(name, arg) __builtin_##name(arg)
15141677typedef unsigned int zig_Builtin64;
15151678#elif LONG_MIN <= INT64_MIN
1516#define zig_builtin64(name, val) __builtin_##name##l(val)
1679#define zig_builtin64(name, arg) __builtin_##name##l(arg)
15171680typedef unsigned long zig_Builtin64;
15181681#elif LLONG_MIN <= INT64_MIN
1519#define zig_builtin64(name, val) __builtin_##name##ll(val)
1682#define zig_builtin64(name, arg) __builtin_##name##ll(arg)
15201683typedef unsigned long long zig_Builtin64;
15211684#endif
15221685
1523static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
1524 return zig_wrap_u8(val >> (8 - bits), bits);
1686#if defined(zig_ez80)
1687#define zig_builtin24(name, arg) __builtin_##name(arg)
1688typedef unsigned int zig_Builtin24;
1689#define zig_builtin48(name, arg) __builtin_##name(arg)
1690typedef unsigned long long zig_Builtin48;
1691#endif
1692
1693static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) {
1694 return zig_u8_truncate_u8(arg >> (8 - bits), bits);
15251695}
15261696
1527static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
1528 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
1697static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) {
1698 return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits);
15291699}
15301700
1531static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
1701static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) {
15321702 uint16_t full_res;
15331703#if zig_has_builtin(bswap16) || defined(zig_gcc)
1534 full_res = __builtin_bswap16(val);
1704 full_res = __builtin_bswap16(arg);
15351705#else
1536 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
1537 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
1706 full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 |
1707 (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0;
15381708#endif
1539 return zig_wrap_u16(full_res >> (16 - bits), bits);
1709 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
15401710}
15411711
1542static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
1543 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
1712static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) {
1713 return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits);
15441714}
15451715
15461716#if defined(zig_ez80)
1547static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) {
1717static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) {
15481718 uint24_t full_res;
15491719#if zig_has_builtin(bswap24) || defined(zig_gcc)
1550 full_res = __builtin_bswap24(val);
1720 full_res = __builtin_bswap24(arg);
15511721#else
1552 full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 |
1553 (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0;
1722 full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 |
1723 (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0;
15541724#endif
1555 return zig_wrap_u24(full_res >> (24 - bits), bits);
1725 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
15561726}
15571727
1558static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) {
1559 return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits);
1728static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) {
1729 return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits);
15601730}
15611731#endif
15621732
1563static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
1733static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) {
15641734 uint32_t full_res;
15651735#if zig_has_builtin(bswap32) || defined(zig_gcc)
1566 full_res = __builtin_bswap32(val);
1736 full_res = __builtin_bswap32(arg);
15671737#else
1568 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
1569 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
1738 full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 |
1739 (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0;
15701740#endif
1571 return zig_wrap_u32(full_res >> (32 - bits), bits);
1741 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
15721742}
15731743
1574static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
1575 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
1744static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) {
1745 return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits);
15761746}
15771747
15781748#if defined(zig_ez80)
1579static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) {
1749static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) {
15801750 uint48_t full_res;
15811751#if zig_has_builtin(bswap48) || defined(zig_gcc)
1582 full_res = __builtin_bswap48(val);
1752 full_res = __builtin_bswap48(arg);
15831753#else
1584 full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 |
1585 (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0;
1754 full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 |
1755 (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0;
15861756#endif
1587 return zig_wrap_u48(full_res >> (48 - bits), bits);
1757 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
15881758}
15891759
1590static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) {
1591 return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits);
1760static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) {
1761 return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits);
15921762}
15931763#endif
15941764
1595static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
1765static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) {
15961766 uint64_t full_res;
15971767#if zig_has_builtin(bswap64) || defined(zig_gcc)
1598 full_res = __builtin_bswap64(val);
1768 full_res = __builtin_bswap64(arg);
15991769#else
1600 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
1601 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
1770 full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 |
1771 (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0;
16021772#endif
1603 return zig_wrap_u64(full_res >> (64 - bits), bits);
1773 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
16041774}
16051775
1606static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
1607 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
1776static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) {
1777 return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits);
16081778}
16091779
1610static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
1780static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) {
16111781 uint8_t full_res;
16121782#if zig_has_builtin(bitreverse8)
1613 full_res = __builtin_bitreverse8(val);
1783 full_res = __builtin_bitreverse8(arg);
16141784#else
16151785 static uint8_t const lut[0x10] = {
16161786 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
16171787 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
16181788 };
1619 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
1789 full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0;
16201790#endif
1621 return zig_wrap_u8(full_res >> (8 - bits), bits);
1791 return zig_u8_truncate_u8(full_res >> (8 - bits), bits);
16221792}
16231793
1624static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
1625 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
1794static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) {
1795 return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits);
16261796}
16271797
1628static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
1798static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) {
16291799 uint16_t full_res;
16301800#if zig_has_builtin(bitreverse16)
1631 full_res = __builtin_bitreverse16(val);
1801 full_res = __builtin_bitreverse16(arg);
16321802#else
1633 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
1634 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
1803 full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 |
1804 (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0;
16351805#endif
1636 return zig_wrap_u16(full_res >> (16 - bits), bits);
1806 return zig_u16_truncate_u16(full_res >> (16 - bits), bits);
16371807}
16381808
1639static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
1640 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
1809static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) {
1810 return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits);
16411811}
16421812
16431813#if defined(zig_ez80)
1644static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) {
1814static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) {
16451815 uint24_t full_res;
16461816#if zig_has_builtin(bitreverse24)
1647 full_res = __builtin_bitreverse24(val);
1817 full_res = __builtin_bitreverse24(arg);
16481818#else
1649 full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 |
1650 (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0;
1819 full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 |
1820 (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0;
16511821#endif
1652 return zig_wrap_u24(full_res >> (24 - bits), bits);
1822 return zig_u24_truncate_u24(full_res >> (24 - bits), bits);
16531823}
16541824
1655static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) {
1656 return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits);
1825static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) {
1826 return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits);
16571827}
16581828#endif
16591829
1660static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
1830static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) {
16611831 uint32_t full_res;
16621832#if zig_has_builtin(bitreverse32)
1663 full_res = __builtin_bitreverse32(val);
1833 full_res = __builtin_bitreverse32(arg);
16641834#else
1665 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
1666 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
1835 full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 |
1836 (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0;
16671837#endif
1668 return zig_wrap_u32(full_res >> (32 - bits), bits);
1838 return zig_u32_truncate_u32(full_res >> (32 - bits), bits);
16691839}
16701840
1671static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
1672 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
1841static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) {
1842 return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits);
16731843}
16741844
16751845#if defined(zig_ez80)
1676static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) {
1846static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) {
16771847 uint48_t full_res;
16781848#if zig_has_builtin(bitreverse48)
1679 full_res = __builtin_bitreverse48(val);
1849 full_res = __builtin_bitreverse48(arg);
16801850#else
1681 full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 |
1682 (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0;
1851 full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 |
1852 (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0;
16831853#endif
1684 return zig_wrap_u32(full_res >> (48 - bits), bits);
1854 return zig_u48_truncate_u48(full_res >> (48 - bits), bits);
16851855}
16861856
1687static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) {
1688 return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits);
1857static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) {
1858 return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits);
16891859}
16901860#endif
16911861
1692static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
1862static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) {
16931863 uint64_t full_res;
16941864#if zig_has_builtin(bitreverse64)
1695 full_res = __builtin_bitreverse64(val);
1865 full_res = __builtin_bitreverse64(arg);
16961866#else
1697 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
1698 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
1867 full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 |
1868 (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0;
16991869#endif
1700 return zig_wrap_u64(full_res >> (64 - bits), bits);
1870 return zig_u64_truncate_u64(full_res >> (64 - bits), bits);
17011871}
17021872
1703static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
1704 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
1873static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) {
1874 return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits);
17051875}
17061876
1707#define zig_builtin_popcount_common(w) \
1708 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
1709 return zig_popcount_u##w((uint##w##_t)val, bits); \
1877#define zig_builtin_popCount_common(w) \
1878 static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \
1879 return zig_popCount_u##w((uint##w##_t)arg, bits); \
17101880 }
1711#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc)
1712#define zig_builtin_popcount(w) \
1713 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1881#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc)
1882#define zig_builtin_popCount(w) \
1883 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17141884 (void)bits; \
1715 return zig_builtin##w(popcount, val); \
1885 return zig_builtin##w(popcount, arg); \
17161886 } \
17171887\
1718 zig_builtin_popcount_common(w)
1888 zig_builtin_popCount_common(w)
17191889#else
1720#define zig_builtin_popcount(w) \
1721 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
1890#define zig_builtin_popCount(w) \
1891 static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \
17221892 (void)bits; \
1723 uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
1893 uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \
17241894 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
17251895 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
17261896 return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
17271897 } \
17281898\
1729 zig_builtin_popcount_common(w)
1730#endif
1731zig_builtin_popcount(8)
1732zig_builtin_popcount(16)
1733#if defined(zig_ez80)
1734zig_builtin_popcount(24)
1899 zig_builtin_popCount_common(w)
17351900#endif
1736zig_builtin_popcount(32)
1901zig_builtin_popCount(8)
1902zig_builtin_popCount(16)
1903zig_builtin_popCount(32)
1904zig_builtin_popCount(64)
17371905#if defined(zig_ez80)
1738zig_builtin_popcount(48)
1906zig_builtin_popCount(24)
1907zig_builtin_popCount(48)
17391908#endif
1740zig_builtin_popcount(64)
17411909
17421910#define zig_builtin_ctz_common(w) \
1743 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
1744 return zig_ctz_u##w((uint##w##_t)val, bits); \
1911 static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \
1912 return zig_ctz_u##w((uint##w##_t)arg, bits); \
17451913 }
17461914#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc)
17471915#define zig_builtin_ctz(w) \
1748 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1749 if (val == 0) return bits; \
1750 return zig_builtin##w(ctz, val); \
1916 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1917 if (arg == 0) return bits; \
1918 return zig_builtin##w(ctz, arg); \
17511919 } \
17521920\
17531921 zig_builtin_ctz_common(w)
17541922#else
17551923#define zig_builtin_ctz(w) \
1756 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
1757 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
1924 static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \
1925 return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \
17581926 } \
17591927\
17601928 zig_builtin_ctz_common(w)
17611929#endif
17621930zig_builtin_ctz(8)
17631931zig_builtin_ctz(16)
1764#if defined(zig_ez80)
1765zig_builtin_ctz(24)
1766#endif
17671932zig_builtin_ctz(32)
1933zig_builtin_ctz(64)
17681934#if defined(zig_ez80)
1935zig_builtin_ctz(24)
17691936zig_builtin_ctz(48)
17701937#endif
1771zig_builtin_ctz(64)
17721938
17731939#define zig_builtin_clz_common(w) \
1774 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
1775 return zig_clz_u##w((uint##w##_t)val, bits); \
1940 static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \
1941 return zig_clz_u##w((uint##w##_t)arg, bits); \
17761942 }
17771943#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc)
17781944#define zig_builtin_clz(w) \
1779 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1780 if (val == 0) return bits; \
1781 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1945 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1946 if (arg == 0) return bits; \
1947 return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
17821948 } \
17831949\
17841950 zig_builtin_clz_common(w)
17851951#else
17861952#define zig_builtin_clz(w) \
1787 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
1788 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
1953 static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \
1954 return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \
17891955 } \
17901956\
17911957 zig_builtin_clz_common(w)
17921958#endif
17931959zig_builtin_clz(8)
17941960zig_builtin_clz(16)
1795#if defined(zig_ez80)
1796zig_builtin_clz(24)
1797#endif
17981961zig_builtin_clz(32)
1962zig_builtin_clz(64)
17991963#if defined(zig_ez80)
1964zig_builtin_clz(24)
18001965zig_builtin_clz(48)
18011966#endif
1802zig_builtin_clz(64)
18031967
18041968/* ======================== 128-bit Integer Support ========================= */
18051969
......@@ -1816,16 +1980,14 @@ zig_builtin_clz(64)
18161980typedef unsigned __int128 zig_u128;
18171981typedef signed __int128 zig_i128;
18181982
1819#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1820#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1821#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1822#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1823#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1824#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1825#define zig_hi_i128(val) (( int64_t)((val) >> 64))
1826#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
1827#define zig_bitCast_u128(val) ((zig_u128)(val))
1828#define zig_bitCast_i128(val) ((zig_i128)(val))
1983#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1984#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1985#define zig_make_u128(hi, lo) zig_init_u128(hi, lo)
1986#define zig_make_i128(hi, lo) zig_init_i128(hi, lo)
1987#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64))
1988#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0))
1989#define zig_hi_i128(arg) (( int64_t)((arg) >> 64))
1990#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0))
18291991#define zig_cmp_int128(Type) \
18301992 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18311993 return (lhs > rhs) - (lhs < rhs); \
......@@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128;
18351997 return lhs operator rhs; \
18361998 }
18371999
1838#else /* zig_has_int128 */
2000static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2001 return lhs << rhs;
2002}
18392003
1840#if zig_little_endian
1841typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1842typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
2004static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2005 return lhs >> rhs;
2006}
2007
2008static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2009 return lhs << rhs;
2010}
2011
2012static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2013 // This works around a GCC miscompilation, but it has the side benefit of
2014 // emitting better code. It is behind the `#if` because it depends on
2015 // arithmetic right shift, which is implementation-defined in C, but should
2016 // be guaranteed on any GCC-compatible compiler.
2017#if defined(zig_gnuc)
2018 return lhs >> rhs;
18432019#else
1844typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1845typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
2020 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
2021 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
18462022#endif
2023}
18472024
1848#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1849#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
2025#else /* zig_has_int128 */
18502026
1851#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */
1852#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1853#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1854#else /* But non-MSVC doesn't like the unprotected commas */
1855#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1856#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1857#endif
1858#define zig_hi_u128(val) ((val).hi)
1859#define zig_lo_u128(val) ((val).lo)
1860#define zig_hi_i128(val) ((val).hi)
1861#define zig_lo_i128(val) ((val).lo)
1862#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
1863#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
2027#if zig_little_endian
2028typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128;
2029typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128;
2030#else
2031typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128;
2032typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128;
2033#endif
2034
2035#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo }
2036#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo }
2037#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo)
2038#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo)
2039#define zig_hi_u128(arg) (arg).hi
2040#define zig_lo_u128(arg) (arg).lo
2041#define zig_hi_i128(arg) (arg).hi
2042#define zig_lo_i128(arg) (arg).lo
18642043#define zig_cmp_int128(Type) \
18652044 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
18662045 return (lhs.hi == rhs.hi) \
......@@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
18722051 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
18732052 }
18742053
2054static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
2055 if (rhs == UINT8_C(0)) return lhs;
2056 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2057 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2058}
2059
2060static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
2061 if (rhs == UINT8_C(0)) return lhs;
2062 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
2063 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
2064}
2065
2066static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2067 if (rhs == UINT8_C(0)) return lhs;
2068 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2069 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2070}
2071
2072static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
2073 if (rhs == UINT8_C(0)) return lhs;
2074 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) };
2075 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2076}
2077
18752078#endif /* zig_has_int128 */
18762079
18772080#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
......@@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |)
18912094zig_bit_int128(u128, xor, ^)
18922095zig_bit_int128(i128, xor, ^)
18932096
1894static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs);
2097static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) {
2098 return (uint8_t)zig_lo_u128(arg);
2099}
2100static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) {
2101 return (uint8_t)zig_lo_i128(arg);
2102}
2103static inline int8_t zig_i8_intCast_i128(zig_i128 arg) {
2104 return (int8_t)zig_lo_i128(arg);
2105}
2106static inline int8_t zig_i8_intCast_u128(zig_u128 arg) {
2107 return (int8_t)zig_lo_u128(arg);
2108}
18952109
1896#if zig_has_int128
2110static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) {
2111 return (uint16_t)zig_lo_u128(arg);
2112}
2113static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) {
2114 return (uint16_t)zig_lo_i128(arg);
2115}
2116static inline int16_t zig_i16_intCast_i128(zig_i128 arg) {
2117 return (int16_t)zig_lo_i128(arg);
2118}
2119static inline int16_t zig_i16_intCast_u128(zig_u128 arg) {
2120 return (int16_t)zig_lo_u128(arg);
2121}
18972122
1898static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1899 return val ^ zig_maxInt_u(128, bits);
2123static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) {
2124 return (uint32_t)zig_lo_u128(arg);
2125}
2126static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) {
2127 return (uint32_t)zig_lo_i128(arg);
2128}
2129static inline int32_t zig_i32_intCast_i128(zig_i128 arg) {
2130 return (int32_t)zig_lo_i128(arg);
2131}
2132static inline int32_t zig_i32_intCast_u128(zig_u128 arg) {
2133 return (int32_t)zig_lo_u128(arg);
19002134}
19012135
1902static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1903 (void)bits;
1904 return ~val;
2136static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) {
2137 return zig_lo_u128(arg);
2138}
2139static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) {
2140 return zig_lo_i128(arg);
2141}
2142static inline int64_t zig_i64_intCast_i128(zig_i128 arg) {
2143 return (int64_t)zig_lo_i128(arg);
2144}
2145static inline int64_t zig_i64_intCast_u128(zig_u128 arg) {
2146 return (int64_t)zig_lo_u128(arg);
19052147}
19062148
1907static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1908 return lhs >> rhs;
2149static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) {
2150 return zig_make_u128(UINT8_C(0), arg);
2151}
2152static inline zig_u128 zig_u128_intCast_i8(int8_t arg) {
2153 return zig_make_u128(UINT8_C(0), (uint8_t)arg);
2154}
2155static inline zig_i128 zig_i128_intCast_i8(int8_t arg) {
2156 return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg);
2157}
2158static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) {
2159 return zig_make_i128(INT8_C(0), arg);
19092160}
19102161
1911static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1912 return lhs << rhs;
2162static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) {
2163 return zig_make_u128(UINT16_C(0), arg);
2164}
2165static inline zig_u128 zig_u128_intCast_i16(int16_t arg) {
2166 return zig_make_u128(UINT16_C(0), (uint16_t)arg);
2167}
2168static inline zig_i128 zig_i128_intCast_i16(int16_t arg) {
2169 return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg);
2170}
2171static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) {
2172 return zig_make_i128(INT16_C(0), arg);
19132173}
19142174
1915static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1916 // This works around a GCC miscompilation, but it has the side benefit of
1917 // emitting better code. It is behind the `#if` because it depends on
1918 // arithmetic right shift, which is implementation-defined in C, but should
1919 // be guaranteed on any GCC-compatible compiler.
1920#if defined(zig_gnuc)
1921 return lhs >> rhs;
2175static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) {
2176 return zig_make_u128(UINT32_C(0), arg);
2177}
2178static inline zig_u128 zig_u128_intCast_i32(int32_t arg) {
2179 return zig_make_u128(UINT32_C(0), (uint32_t)arg);
2180}
2181static inline zig_i128 zig_i128_intCast_i32(int32_t arg) {
2182 return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg);
2183}
2184static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) {
2185 return zig_make_i128(INT32_C(0), arg);
2186}
2187
2188static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) {
2189 return zig_make_u128(UINT64_C(0), arg);
2190}
2191static inline zig_u128 zig_u128_intCast_i64(int64_t arg) {
2192 return zig_make_u128(UINT64_C(0), (uint64_t)arg);
2193}
2194static inline zig_i128 zig_i128_intCast_i64(int64_t arg) {
2195 return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg);
2196}
2197static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) {
2198 return zig_make_i128(INT64_C(0), arg);
2199}
2200
2201static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) {
2202 return arg;
2203}
2204static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) {
2205#if zig_has_int128
2206 return (zig_u128)arg;
19222207#else
1923 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1924 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
2208 return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
2209#endif
2210}
2211static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) {
2212 return arg;
2213}
2214static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) {
2215#if zig_has_int128
2216 return (zig_i128)arg;
2217#else
2218 return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg));
19252219#endif
19262220}
19272221
1928static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
1929 return lhs << rhs;
2222#define zig_int128_cast_builtins(w) \
2223 static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \
2224 return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \
2225 } \
2226\
2227 static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \
2228 return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \
2229 }
2230zig_int128_cast_builtins(8)
2231zig_int128_cast_builtins(16)
2232zig_int128_cast_builtins(32)
2233zig_int128_cast_builtins(64)
2234
2235static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) {
2236 return zig_and_u128(arg, zig_maxInt_u(128, bits));
2237}
2238static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) {
2239 if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg));
2240 int64_t lo = zig_i64_truncate_i128(arg, bits);
2241 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2242}
2243
2244static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2245 (void)bits;
2246 return arg;
2247}
2248static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2249 return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits);
2250}
2251static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) {
2252 (void)bits;
2253 return arg;
2254}
2255static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) {
2256 return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits);
2257}
2258
2259#if zig_has_int128
2260
2261static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2262 return arg ^ zig_maxInt_u(128, bits);
2263}
2264
2265static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2266 (void)bits;
2267 return ~arg;
19302268}
19312269
19322270static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
......@@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
19532291 return lhs * rhs;
19542292}
19552293
1956static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2294static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
19572295 return lhs / rhs;
19582296}
19592297
1960static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2298static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
19612299 return lhs / rhs;
19622300}
19632301
......@@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
19712309
19722310#else /* zig_has_int128 */
19732311
1974static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1975 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1976}
1977
1978static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1979 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1980}
1981
1982static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1983 if (rhs == UINT8_C(0)) return lhs;
1984 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
1985 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
1986}
1987
1988static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1989 if (rhs == UINT8_C(0)) return lhs;
1990 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1991 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
1992}
1993
1994static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1995 if (rhs == UINT8_C(0)) return lhs;
1996 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) };
1997 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
2312static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) {
2313 if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) };
2314 return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) };
19982315}
19992316
2000static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
2001 if (rhs == UINT8_C(0)) return lhs;
2002 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
2003 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
2317static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) {
2318 (void)bits;
2319 return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo };
20042320}
20052321
20062322static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
......@@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
20272343 return res;
20282344}
20292345
2030zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20312346static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
2347 zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
20322348 return __multi3(lhs, rhs);
20332349}
20342350
20352351static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
2036 return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs)));
2352 return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128));
20372353}
20382354
2039zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
2040static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
2355static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) {
2356 zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
20412357 return __udivti3(lhs, rhs);
20422358}
20432359
2044zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
2045static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
2360static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) {
2361 zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
20462362 return __divti3(lhs, rhs);
20472363}
20482364
2049zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20502365static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
2366 zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
20512367 return __umodti3(lhs, rhs);
20522368}
20532369
2054zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20552370static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
2371 zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
20562372 return __modti3(lhs, rhs);
20572373}
20582374
20592375#endif /* zig_has_int128 */
20602376
2061#define zig_div_floor_u128 zig_div_trunc_u128
2377#define zig_divFloor_u128 zig_divTrunc_u128
20622378
2063static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
2379static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) {
20642380 zig_i128 rem = zig_rem_i128(lhs, rhs);
20652381 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20662382 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);
2067 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
2383 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
20682384}
20692385
2070static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) {
2386static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) {
20712387 zig_u128 rem = zig_rem_u128(lhs, rhs);
20722388 uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0)
20732389 ? UINT64_C(1) : UINT64_C(0);
2074 return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
2390 return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask));
20752391}
20762392
2077static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) {
2393static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) {
20782394 zig_i128 rem = zig_rem_i128(lhs, rhs);
20792395 int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
20802396 ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1)
20812397 : INT64_C(0);
2082 return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
2398 return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask));
20832399}
20842400
20852401#define zig_mod_u128 zig_rem_u128
......@@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
21072423 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
21082424}
21092425
2110static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
2111 return zig_and_u128(val, zig_maxInt_u(128, bits));
2112}
2113
2114static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
2115 if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
2116 int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits);
2117 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
2118}
2119
21202426static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
2121 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
2427 return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits);
21222428}
21232429
21242430static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {
2125 return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits);
2431 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits);
21262432}
21272433
21282434static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2129 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
2435 return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits);
21302436}
21312437
21322438static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2133 return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2439 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits);
21342440}
21352441
21362442static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2137 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
2443 return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits);
21382444}
21392445
21402446static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2141 return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2447 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits);
21422448}
21432449
21442450static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2145 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
2451 return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits);
21462452}
21472453
21482454static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2149 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
2455 return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits);
21502456}
21512457
2152static inline zig_u128 zig_abs_i128(zig_i128 val) {
2153 zig_i128 tmp = zig_shr_i128(val, 127);
2154 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));
2458static inline zig_u128 zig_abs_i128(zig_i128 arg) {
2459 zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128));
2460 return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp);
21552461}
21562462
21572463#if zig_has_int128
......@@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21602466#if zig_has_builtin(add_overflow)
21612467 zig_u128 full_res;
21622468 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
2163 *res = zig_wrap_u128(full_res, bits);
2469 *res = zig_u128_truncate_u128(full_res, bits);
21642470 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21652471#else
21662472 *res = zig_addw_u128(lhs, rhs, bits);
......@@ -2176,7 +2482,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
21762482 zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs);
21772483 bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0;
21782484#endif
2179 *res = zig_wrap_i128(full_res, bits);
2485 *res = zig_i128_truncate_i128(full_res, bits);
21802486 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
21812487}
21822488
......@@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
21842490#if zig_has_builtin(sub_overflow)
21852491 zig_u128 full_res;
21862492 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
2187 *res = zig_wrap_u128(full_res, bits);
2493 *res = zig_u128_truncate_u128(full_res, bits);
21882494 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
21892495#else
21902496 *res = zig_subw_u128(lhs, rhs, bits);
......@@ -2200,7 +2506,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
22002506 zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs);
22012507 bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0;
22022508#endif
2203 *res = zig_wrap_i128(full_res, bits);
2509 *res = zig_i128_truncate_i128(full_res, bits);
22042510 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22052511}
22062512
......@@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
22082514#if zig_has_builtin(mul_overflow)
22092515 zig_u128 full_res;
22102516 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
2211 *res = zig_wrap_u128(full_res, bits);
2517 *res = zig_u128_truncate_u128(full_res, bits);
22122518 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
22132519#else
22142520 *res = zig_mulw_u128(lhs, rhs, bits);
......@@ -2216,8 +2522,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint
22162522#endif
22172523}
22182524
2219zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22202525static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2526 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22212527#if zig_has_builtin(mul_overflow)
22222528 zig_i128 full_res;
22232529 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
......@@ -2226,50 +2532,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint
22262532 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22272533 bool overflow = overflow_int != 0;
22282534#endif
2229 *res = zig_wrap_i128(full_res, bits);
2535 *res = zig_i128_truncate_i128(full_res, bits);
22302536 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
22312537}
22322538
22332539#else /* zig_has_int128 */
22342540
22352541static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2236 uint64_t hi;
2237 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2238 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2542 if (bits <= UINT8_C(64)) {
2543 uint64_t lo;
2544 bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2545 *res = zig_u128_intCast_u64(lo);
2546 return overflow;
2547 } else {
2548 uint64_t hi;
2549 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2550 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2551 }
22392552}
22402553
22412554static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2242 int64_t hi;
2243 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2244 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2555 if (bits <= UINT8_C(64)) {
2556 int64_t lo;
2557 bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2558 *res = zig_i128_intCast_i64(lo);
2559 return overflow;
2560 } else {
2561 int64_t hi;
2562 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2563 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2564 }
22452565}
22462566
22472567static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2248 uint64_t hi;
2249 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
2250 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2568 if (bits <= UINT8_C(64)) {
2569 uint64_t lo;
2570 bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits);
2571 *res = zig_u128_intCast_u64(lo);
2572 return overflow;
2573 } else {
2574 uint64_t hi;
2575 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2576 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2577 }
22512578}
22522579
22532580static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2254 int64_t hi;
2255 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
2256 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
2581 if (bits <= UINT8_C(64)) {
2582 int64_t lo;
2583 bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits);
2584 *res = zig_i128_intCast_i64(lo);
2585 return overflow;
2586 } else {
2587 int64_t hi;
2588 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64));
2589 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64));
2590 }
22572591}
22582592
22592593static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22602594 *res = zig_mulw_u128(lhs, rhs, bits);
2261 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
2262 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
2595 return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) &&
2596 zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
22632597}
22642598
2265zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22662599static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
2600 zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
22672601 int overflow_int;
22682602 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
22692603 bool overflow = overflow_int != 0 ||
22702604 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
22712605 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);
2272 *res = zig_wrap_i128(full_res, bits);
2606 *res = zig_i128_truncate_i128(full_res, bits);
22732607 return overflow;
22742608}
22752609
......@@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8
22822616
22832617static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
22842618 *res = zig_shlw_i128(lhs, rhs, bits);
2285 zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
2619 zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits);
22862620 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
22872621 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
22882622}
22892623
2290static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
2624#define zig_int128_shls_builtins(rw) \
2625 static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2626 zig_u128 res; \
2627 if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2628 switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \
2629 case 0: return zig_minInt_u(128, bits); \
2630 case 1: return zig_maxInt_u(128, bits); \
2631 default: zig_unreachable(); \
2632 } \
2633 } \
2634\
2635 static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \
2636 zig_i128 res; \
2637 if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \
2638 switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \
2639 case -1: return zig_minInt_i(128, bits); \
2640 case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \
2641 case 1: return zig_maxInt_i(128, bits); \
2642 default: zig_unreachable(); \
2643 } \
2644 }
2645zig_int128_shls_builtins(8)
2646zig_int128_shls_builtins(16)
2647zig_int128_shls_builtins(32)
2648zig_int128_shls_builtins(64)
2649
2650static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
22912651 zig_u128 res;
22922652 if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res;
22932653 switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) {
2294 case 0: return zig_make_u128(0, 0);
2295 case 1: return zig_maxInt_u(128, bits);
2654 case INT32_C(0): return zig_make_u128(0, 0);
2655 case INT32_C(1): return zig_maxInt_u(128, bits);
22962656 default: zig_unreachable();
22972657 }
22982658}
22992659
2300static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
2660static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) {
23012661 zig_i128 res;
23022662 if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res;
23032663 switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) {
2304 case -1: return zig_minInt_i(128, bits);
2305 case 0: return zig_make_i128(0, 0);
2306 case 1: return zig_maxInt_i(128, bits);
2664 case -INT32_C(1): return zig_minInt_i(128, bits);
2665 case INT32_C(0): return zig_make_i128(0, 0);
2666 case INT32_C(1): return zig_maxInt_i(128, bits);
23072667 default: zig_unreachable();
23082668 }
23092669}
......@@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
23412701 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
23422702}
23432703
2344static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
2345 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);
2346 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
2347 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
2704static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) {
2705 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits);
2706 if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64));
2707 return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64));
23482708}
23492709
2350static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {
2351 return zig_clz_u128(zig_bitCast_u128(val), bits);
2710static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) {
2711 return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23522712}
23532713
2354static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
2355 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
2356 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
2714static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) {
2715 if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64));
2716 return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64);
23572717}
23582718
2359static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {
2360 return zig_ctz_u128(zig_bitCast_u128(val), bits);
2719static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) {
2720 return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits);
23612721}
23622722
2363static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
2364 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
2365 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
2723static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) {
2724 return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) +
2725 zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64));
23662726}
23672727
2368static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {
2369 return zig_popcount_u128(zig_bitCast_u128(val), bits);
2728static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) {
2729 return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits);
23702730}
23712731
2372static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) {
2732static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) {
23732733 zig_u128 full_res;
23742734#if zig_has_builtin(bswap128)
2375 full_res = __builtin_bswap128(val);
2735 full_res = __builtin_bswap128(arg);
23762736#else
2377 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
2378 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
2737 full_res = zig_make_u128(
2738 zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)),
2739 zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64))
2740 );
23792741#endif
23802742 return zig_shr_u128(full_res, UINT8_C(128) - bits);
23812743}
23822744
2383static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {
2384 return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));
2745static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) {
2746 return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23852747}
23862748
2387static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
2388 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
2389 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
2390 UINT8_C(128) - bits);
2749static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) {
2750 return zig_shr_u128(zig_make_u128(
2751 zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)),
2752 zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64))
2753 ), UINT8_C(128) - bits);
23912754}
23922755
2393static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
2394 return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));
2756static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) {
2757 return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits);
23952758}
23962759
23972760#if zig_has_int128
......@@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
24112774/* ========================== Big Integer Support =========================== */
24122775
24132776static inline uint16_t zig_int_bytes(uint16_t bits) {
2414 uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT;
2777 uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1);
24152778 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
2779
24162780 while (alignment / 2 >= bytes) alignment /= 2;
24172781 return (bytes + alignment - 1) / alignment * alignment;
24182782}
24192783
2420static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2784static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) {
2785 uint8_t *res_bytes = res;
2786 uint16_t size = zig_int_bytes(bits);
2787 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2788 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2789 uint8_t sign_byte;
2790 uint8_t fill_byte;
2791
2792 if (is_signed) {
2793 int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits);
2794
2795 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2796 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2797 } else {
2798 sign_byte = zig_minInt_u(8, remainder_bits);
2799 fill_byte = UINT8_C(0);
2800 }
2801
2802#if zig_little_endian
2803 memset(&res_bytes[0], zig_minInt_u8, byte_offset);
2804 res_bytes[byte_offset] = sign_byte;
2805 byte_offset += UINT16_C(1);
2806 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2807#else
2808 byte_offset = size - UINT16_C(1) - byte_offset;
2809 memset(&res_bytes[0], fill_byte, byte_offset);
2810 res_bytes[byte_offset] = sign_byte;
2811 byte_offset += UINT16_C(1);
2812 memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset);
2813#endif
2814}
2815
2816static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) {
2817 uint8_t *res_bytes = res;
2818 uint16_t size = zig_int_bytes(bits);
2819 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2820 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2821 uint8_t sign_byte;
2822 uint8_t fill_byte;
2823
2824 if (is_signed) {
2825 int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits);
2826
2827 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2828 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2829 } else {
2830 sign_byte = zig_maxInt_u(8, remainder_bits);
2831 fill_byte = UINT8_C(0);
2832 }
2833
2834#if zig_little_endian
2835 memset(&res_bytes[0], zig_maxInt_u8, byte_offset);
2836 res_bytes[byte_offset] = sign_byte;
2837 byte_offset += UINT16_C(1);
2838 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2839#else
2840 byte_offset = size - UINT16_C(1) - byte_offset;
2841 memset(&res_bytes[0], fill_byte, byte_offset);
2842 res_bytes[byte_offset] = sign_byte;
2843 byte_offset += UINT16_C(1);
2844 memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset);
2845#endif
2846}
2847
2848static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) {
2849 const uint8_t *arg_bytes = arg;
2850 uint16_t byte_offset = 0;
2851
2852 if (!is_signed) return INT8_C(0);
2853#if zig_little_endian
2854 byte_offset = zig_int_bytes(bits) - 1;
2855#endif
2856 return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7));
2857}
2858
2859static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) {
2860 uint8_t *res_bytes = res;
2861 const uint8_t *arg_bytes = arg;
2862 uint16_t res_size = zig_int_bytes(res_bits);
2863 uint16_t arg_size = zig_int_bytes(arg_bits);
2864 uint16_t copy_size = zig_min_u16(res_size, arg_size);
2865 uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8));
2866
2867#if zig_little_endian
2868 memcpy(&res_bytes[0], &arg_bytes[0], copy_size);
2869 memset(&res_bytes[copy_size], sign_fill, res_size - copy_size);
2870#else
2871 memset(&res_bytes[0], sign_fill, res_size - copy_size);
2872 memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size);
2873#endif
2874}
2875
2876static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) {
2877 uint8_t *res_bytes = res;
2878 const uint8_t *arg_bytes = arg;
2879 uint16_t res_size = zig_int_bytes(res_bits);
2880
2881 if (res_is_signed != arg_is_signed) zig_unreachable();
2882 if (res_bits > arg_bits) zig_unreachable();
2883
2884 if (res_is_signed) {
2885 uint16_t arg_byte_offset = UINT16_C(0);
2886
2887#if zig_big_endian
2888 arg_byte_offset = zig_int_bytes(arg_bits) - res_size;
2889#endif
2890
2891 memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size);
2892 } else {
2893 uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3));
2894 uint16_t arg_byte_offset = res_byte_offset;
2895
2896#if zig_little_endian
2897 memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset);
2898#else
2899 res_byte_offset = res_size - UINT16_C(1) - res_byte_offset;
2900 arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset;
2901
2902 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
2903#endif
2904
2905 res_bytes[res_byte_offset] = zig_u8_truncate_u8(
2906 arg_bytes[arg_byte_offset],
2907 zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1)
2908 );
2909 res_byte_offset += UINT16_C(1);
2910 arg_byte_offset += UINT16_C(1);
2911
2912#if zig_little_endian
2913 memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset);
2914#else
2915 memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset);
2916#endif
2917 }
2918}
2919
2920#define zig_big_casts(is, s, w, IntType) \
2921 static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \
2922 IntType res; \
2923 zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \
2924 return res; \
2925 } \
2926\
2927 static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2928 zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \
2929 } \
2930\
2931 static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \
2932 IntType res; \
2933 zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \
2934 return res; \
2935 } \
2936\
2937 static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \
2938 zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \
2939 }
2940zig_big_casts(false, u, 8, uint8_t)
2941zig_big_casts(true , i, 8, int8_t)
2942zig_big_casts(false, u, 16, uint16_t)
2943zig_big_casts(true , i, 16, int16_t)
2944zig_big_casts(false, u, 32, uint32_t)
2945zig_big_casts(true , i, 32, int32_t)
2946zig_big_casts(false, u, 64, uint64_t)
2947zig_big_casts(true , i, 64, int64_t)
2948zig_big_casts(false, u, 128, zig_u128)
2949zig_big_casts(true , i, 128, zig_i128)
2950
2951static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) {
2952 uint8_t *res_bytes = res;
2953 const uint8_t *arg_bytes = arg;
2954 uint16_t size = zig_int_bytes(bits);
2955 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3));
2956 uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1);
2957 uint8_t sign_byte;
2958 uint8_t fill_byte;
2959
2960#if zig_big_endian
2961 byte_offset = size - UINT16_C(1) - byte_offset;
2962#endif
2963
2964 if (res_is_signed) {
2965 int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2966
2967 sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8));
2968 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8));
2969 } else {
2970 sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits);
2971 fill_byte = UINT8_C(0);
2972 }
2973
2974#if zig_little_endian
2975 memcpy(&res_bytes[0], &arg_bytes[0], byte_offset);
2976 res_bytes[byte_offset] = sign_byte;
2977 byte_offset += UINT16_C(1);
2978 memset(&res_bytes[byte_offset], fill_byte, size - byte_offset);
2979#else
2980 memset(&res_bytes[0], fill_byte, byte_offset);
2981 res_bytes[byte_offset] = sign_byte;
2982 byte_offset += UINT16_C(1);
2983 memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset);
2984#endif
2985}
2986
2987static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) {
24212988 const uint8_t *lhs_bytes = lhs;
2422 const uint8_t *rhs_bytes = rhs;
24232989 uint16_t byte_offset = 0;
24242990 bool do_signed = is_signed;
24252991 uint16_t remaining_bytes = zig_int_bytes(bits);
......@@ -2429,6 +2995,7 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24292995#endif
24302996
24312997 while (remaining_bytes >= 128 / CHAR_BIT) {
2998 uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0);
24322999 int32_t limb_cmp;
24333000
24343001#if zig_little_endian
......@@ -2437,18 +3004,16 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24373004
24383005 if (do_signed) {
24393006 zig_i128 lhs_limb;
2440 zig_i128 rhs_limb;
3007 zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte);
24413008
24423009 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2443 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24443010 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
24453011 do_signed = false;
24463012 } else {
24473013 zig_u128 lhs_limb;
2448 zig_u128 rhs_limb;
3014 zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte);
24493015
24503016 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2451 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24523017 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
24533018 }
24543019
......@@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24613026 }
24623027
24633028 while (remaining_bytes >= 64 / CHAR_BIT) {
3029 uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0);
3030
24643031#if zig_little_endian
24653032 byte_offset -= 64 / CHAR_BIT;
24663033#endif
24673034
24683035 if (do_signed) {
24693036 int64_t lhs_limb;
2470 int64_t rhs_limb;
3037 int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte);
24713038
24723039 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2473 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24743040 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24753041 do_signed = false;
24763042 } else {
24773043 uint64_t lhs_limb;
2478 uint64_t rhs_limb;
3044 uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte);
24793045
24803046 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2481 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
24823047 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
24833048 }
24843049
......@@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
24903055 }
24913056
24923057 while (remaining_bytes >= 32 / CHAR_BIT) {
3058 uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0);
3059
24933060#if zig_little_endian
24943061 byte_offset -= 32 / CHAR_BIT;
24953062#endif
24963063
24973064 if (do_signed) {
24983065 int32_t lhs_limb;
2499 int32_t rhs_limb;
3066 int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte);
25003067
25013068 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2502 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25033069 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25043070 do_signed = false;
25053071 } else {
25063072 uint32_t lhs_limb;
2507 uint32_t rhs_limb;
3073 uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte);
25083074
25093075 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2510 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25113076 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25123077 }
25133078
......@@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25193084 }
25203085
25213086 while (remaining_bytes >= 16 / CHAR_BIT) {
3087 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3088
25223089#if zig_little_endian
25233090 byte_offset -= 16 / CHAR_BIT;
25243091#endif
25253092
25263093 if (do_signed) {
25273094 int16_t lhs_limb;
2528 int16_t rhs_limb;
3095 int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte);
25293096
25303097 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2531 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25323098 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25333099 do_signed = false;
25343100 } else {
25353101 uint16_t lhs_limb;
2536 uint16_t rhs_limb;
3102 uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte);
25373103
25383104 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2539 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25403105 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25413106 }
25423107
......@@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25483113 }
25493114
25503115 while (remaining_bytes >= 8 / CHAR_BIT) {
3116 uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0);
3117
25513118#if zig_little_endian
25523119 byte_offset -= 8 / CHAR_BIT;
25533120#endif
25543121
25553122 if (do_signed) {
25563123 int8_t lhs_limb;
2557 int8_t rhs_limb;
3124 int16_t lhs_cmp_limb;
3125 int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte);
25583126
25593127 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2560 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2561 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3128 lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb);
3129 if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb);
25623130 do_signed = false;
25633131 } else {
25643132 uint8_t lhs_limb;
2565 uint8_t rhs_limb;
3133 uint8_t rhs_limb = rhs_byte;
25663134
25673135 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2568 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
25693136 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
25703137 }
25713138
......@@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign
25793146 return 0;
25803147}
25813148
2582static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2583 uint8_t *res_bytes = res;
3149static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
25843150 const uint8_t *lhs_bytes = lhs;
25853151 const uint8_t *rhs_bytes = rhs;
25863152 uint16_t byte_offset = 0;
3153 bool do_signed = is_signed;
25873154 uint16_t remaining_bytes = zig_int_bytes(bits);
2588 (void)is_signed;
3155
3156#if zig_little_endian
3157 byte_offset = remaining_bytes;
3158#endif
25893159
25903160 while (remaining_bytes >= 128 / CHAR_BIT) {
2591 zig_u128 res_limb;
2592 zig_u128 lhs_limb;
2593 zig_u128 rhs_limb;
3161 int32_t limb_cmp;
25943162
2595 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2596 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2597 res_limb = zig_and_u128(lhs_limb, rhs_limb);
2598 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3163#if zig_little_endian
3164 byte_offset -= 128 / CHAR_BIT;
3165#endif
3166
3167 if (do_signed) {
3168 zig_i128 lhs_limb;
3169 zig_i128 rhs_limb;
3170
3171 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3172 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3173 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
3174 do_signed = false;
3175 } else {
3176 zig_u128 lhs_limb;
3177 zig_u128 rhs_limb;
3178
3179 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3180 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3181 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
3182 }
25993183
3184 if (limb_cmp != 0) return limb_cmp;
26003185 remaining_bytes -= 128 / CHAR_BIT;
3186
3187#if zig_big_endian
26013188 byte_offset += 128 / CHAR_BIT;
3189#endif
26023190 }
26033191
26043192 while (remaining_bytes >= 64 / CHAR_BIT) {
2605 uint64_t res_limb;
2606 uint64_t lhs_limb;
2607 uint64_t rhs_limb;
3193#if zig_little_endian
3194 byte_offset -= 64 / CHAR_BIT;
3195#endif
26083196
2609 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2610 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2611 res_limb = zig_and_u64(lhs_limb, rhs_limb);
2612 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3197 if (do_signed) {
3198 int64_t lhs_limb;
3199 int64_t rhs_limb;
3200
3201 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3202 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3203 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3204 do_signed = false;
3205 } else {
3206 uint64_t lhs_limb;
3207 uint64_t rhs_limb;
3208
3209 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3210 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3211 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3212 }
26133213
26143214 remaining_bytes -= 64 / CHAR_BIT;
3215
3216#if zig_big_endian
26153217 byte_offset += 64 / CHAR_BIT;
3218#endif
26163219 }
26173220
26183221 while (remaining_bytes >= 32 / CHAR_BIT) {
2619 uint32_t res_limb;
2620 uint32_t lhs_limb;
2621 uint32_t rhs_limb;
3222#if zig_little_endian
3223 byte_offset -= 32 / CHAR_BIT;
3224#endif
26223225
2623 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2624 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2625 res_limb = zig_and_u32(lhs_limb, rhs_limb);
2626 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3226 if (do_signed) {
3227 int32_t lhs_limb;
3228 int32_t rhs_limb;
3229
3230 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3231 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3232 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3233 do_signed = false;
3234 } else {
3235 uint32_t lhs_limb;
3236 uint32_t rhs_limb;
3237
3238 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3239 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3240 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3241 }
26273242
26283243 remaining_bytes -= 32 / CHAR_BIT;
3244
3245#if zig_big_endian
26293246 byte_offset += 32 / CHAR_BIT;
3247#endif
26303248 }
26313249
26323250 while (remaining_bytes >= 16 / CHAR_BIT) {
2633 uint16_t res_limb;
2634 uint16_t lhs_limb;
2635 uint16_t rhs_limb;
3251#if zig_little_endian
3252 byte_offset -= 16 / CHAR_BIT;
3253#endif
26363254
2637 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2638 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2639 res_limb = zig_and_u16(lhs_limb, rhs_limb);
2640 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3255 if (do_signed) {
3256 int16_t lhs_limb;
3257 int16_t rhs_limb;
3258
3259 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3260 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3261 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3262 do_signed = false;
3263 } else {
3264 uint16_t lhs_limb;
3265 uint16_t rhs_limb;
3266
3267 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3268 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3269 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3270 }
26413271
26423272 remaining_bytes -= 16 / CHAR_BIT;
3273
3274#if zig_big_endian
26433275 byte_offset += 16 / CHAR_BIT;
3276#endif
26443277 }
26453278
26463279 while (remaining_bytes >= 8 / CHAR_BIT) {
2647 uint8_t res_limb;
2648 uint8_t lhs_limb;
2649 uint8_t rhs_limb;
3280#if zig_little_endian
3281 byte_offset -= 8 / CHAR_BIT;
3282#endif
26503283
2651 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2652 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2653 res_limb = zig_and_u8(lhs_limb, rhs_limb);
2654 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3284 if (do_signed) {
3285 int8_t lhs_limb;
3286 int8_t rhs_limb;
3287
3288 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3289 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3290 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3291 do_signed = false;
3292 } else {
3293 uint8_t lhs_limb;
3294 uint8_t rhs_limb;
3295
3296 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3297 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3298 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
3299 }
26553300
26563301 remaining_bytes -= 8 / CHAR_BIT;
3302
3303#if zig_big_endian
26573304 byte_offset += 8 / CHAR_BIT;
3305#endif
26583306 }
3307
3308 return 0;
26593309}
26603310
2661static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3311static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
26623312 uint8_t *res_bytes = res;
2663 const uint8_t *lhs_bytes = lhs;
2664 const uint8_t *rhs_bytes = rhs;
3313 const uint8_t *arg_bytes = arg;
26653314 uint16_t byte_offset = 0;
26663315 uint16_t remaining_bytes = zig_int_bytes(bits);
2667 (void)is_signed;
3316 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3317
3318#if zig_big_endian
3319 byte_offset = remaining_bytes;
3320#endif
26683321
26693322 while (remaining_bytes >= 128 / CHAR_BIT) {
2670 zig_u128 res_limb;
2671 zig_u128 lhs_limb;
2672 zig_u128 rhs_limb;
3323 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
26733324
2674 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2675 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2676 res_limb = zig_or_u128(lhs_limb, rhs_limb);
2677 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3325#if zig_big_endian
3326 byte_offset -= 128 / CHAR_BIT;
3327#endif
3328
3329 if (remaining_bytes != 128 / CHAR_BIT || is_signed) {
3330 zig_i128 res_limb;
3331 zig_i128 arg_limb;
3332
3333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3334 res_limb = zig_not_i128(arg_limb, limb_bits);
3335 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3336 } else {
3337 zig_u128 res_limb;
3338 zig_u128 arg_limb;
3339
3340 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3341 res_limb = zig_not_u128(arg_limb, limb_bits);
3342 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3343 }
26783344
26793345 remaining_bytes -= 128 / CHAR_BIT;
3346
3347#if zig_little_endian
26803348 byte_offset += 128 / CHAR_BIT;
3349#endif
26813350 }
26823351
26833352 while (remaining_bytes >= 64 / CHAR_BIT) {
2684 uint64_t res_limb;
2685 uint64_t lhs_limb;
2686 uint64_t rhs_limb;
3353 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
26873354
2688 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2689 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2690 res_limb = zig_or_u64(lhs_limb, rhs_limb);
2691 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3355#if zig_big_endian
3356 byte_offset -= 64 / CHAR_BIT;
3357#endif
3358
3359 if (remaining_bytes != 64 / CHAR_BIT || is_signed) {
3360 int64_t res_limb;
3361 int64_t arg_limb;
3362
3363 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3364 res_limb = zig_not_i64(arg_limb, limb_bits);
3365 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3366 } else {
3367 uint64_t res_limb;
3368 uint64_t arg_limb;
3369
3370 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3371 res_limb = zig_not_u64(arg_limb, limb_bits);
3372 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3373 }
26923374
26933375 remaining_bytes -= 64 / CHAR_BIT;
3376
3377#if zig_little_endian
26943378 byte_offset += 64 / CHAR_BIT;
3379#endif
26953380 }
26963381
26973382 while (remaining_bytes >= 32 / CHAR_BIT) {
2698 uint32_t res_limb;
2699 uint32_t lhs_limb;
2700 uint32_t rhs_limb;
3383 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
27013384
2702 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2703 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2704 res_limb = zig_or_u32(lhs_limb, rhs_limb);
2705 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3385#if zig_big_endian
3386 byte_offset -= 32 / CHAR_BIT;
3387#endif
3388
3389 if (remaining_bytes != 32 / CHAR_BIT || is_signed) {
3390 int32_t res_limb;
3391 int32_t arg_limb;
3392
3393 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3394 res_limb = zig_not_i32(arg_limb, limb_bits);
3395 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3396 } else {
3397 uint32_t res_limb;
3398 uint32_t arg_limb;
3399
3400 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3401 res_limb = zig_not_u32(arg_limb, limb_bits);
3402 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3403 }
27063404
27073405 remaining_bytes -= 32 / CHAR_BIT;
3406
3407#if zig_little_endian
27083408 byte_offset += 32 / CHAR_BIT;
3409#endif
27093410 }
27103411
27113412 while (remaining_bytes >= 16 / CHAR_BIT) {
2712 uint16_t res_limb;
2713 uint16_t lhs_limb;
2714 uint16_t rhs_limb;
3413 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
27153414
2716 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2717 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2718 res_limb = zig_or_u16(lhs_limb, rhs_limb);
2719 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3415#if zig_big_endian
3416 byte_offset -= 16 / CHAR_BIT;
3417#endif
27203418
2721 remaining_bytes -= 16 / CHAR_BIT;
2722 byte_offset += 16 / CHAR_BIT;
2723 }
3419 if (remaining_bytes != 16 / CHAR_BIT || is_signed) {
3420 int16_t res_limb;
3421 int16_t arg_limb;
3422
3423 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3424 res_limb = zig_not_i16(arg_limb, limb_bits);
3425 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3426 } else {
3427 uint16_t res_limb;
3428 uint16_t arg_limb;
3429
3430 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3431 res_limb = zig_not_u16(arg_limb, limb_bits);
3432 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3433 }
3434
3435 remaining_bytes -= 16 / CHAR_BIT;
3436
3437#if zig_little_endian
3438 byte_offset += 16 / CHAR_BIT;
3439#endif
3440 }
3441
3442 while (remaining_bytes >= 8 / CHAR_BIT) {
3443 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3444
3445#if zig_big_endian
3446 byte_offset -= 8 / CHAR_BIT;
3447#endif
3448
3449 if (remaining_bytes != 8 / CHAR_BIT || is_signed) {
3450 int8_t res_limb;
3451 int8_t arg_limb;
3452
3453 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3454 res_limb = zig_not_i8(arg_limb, limb_bits);
3455 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3456 } else {
3457 uint8_t res_limb;
3458 uint8_t arg_limb;
3459
3460 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
3461 res_limb = zig_not_u8(arg_limb, limb_bits);
3462 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3463 }
3464
3465 remaining_bytes -= 8 / CHAR_BIT;
3466
3467#if zig_little_endian
3468 byte_offset += 8 / CHAR_BIT;
3469#endif
3470 }
3471}
3472
3473static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3474 uint8_t *res_bytes = res;
3475 const uint8_t *lhs_bytes = lhs;
3476 const uint8_t *rhs_bytes = rhs;
3477 uint16_t byte_offset = 0;
3478 uint16_t remaining_bytes = zig_int_bytes(bits);
3479 (void)is_signed;
3480
3481 while (remaining_bytes >= 128 / CHAR_BIT) {
3482 zig_u128 res_limb;
3483 zig_u128 lhs_limb;
3484 zig_u128 rhs_limb;
3485
3486 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3487 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3488 res_limb = zig_and_u128(lhs_limb, rhs_limb);
3489 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3490
3491 remaining_bytes -= 128 / CHAR_BIT;
3492 byte_offset += 128 / CHAR_BIT;
3493 }
3494
3495 while (remaining_bytes >= 64 / CHAR_BIT) {
3496 uint64_t res_limb;
3497 uint64_t lhs_limb;
3498 uint64_t rhs_limb;
3499
3500 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3501 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3502 res_limb = zig_and_u64(lhs_limb, rhs_limb);
3503 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3504
3505 remaining_bytes -= 64 / CHAR_BIT;
3506 byte_offset += 64 / CHAR_BIT;
3507 }
3508
3509 while (remaining_bytes >= 32 / CHAR_BIT) {
3510 uint32_t res_limb;
3511 uint32_t lhs_limb;
3512 uint32_t rhs_limb;
3513
3514 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3515 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3516 res_limb = zig_and_u32(lhs_limb, rhs_limb);
3517 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3518
3519 remaining_bytes -= 32 / CHAR_BIT;
3520 byte_offset += 32 / CHAR_BIT;
3521 }
3522
3523 while (remaining_bytes >= 16 / CHAR_BIT) {
3524 uint16_t res_limb;
3525 uint16_t lhs_limb;
3526 uint16_t rhs_limb;
3527
3528 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3529 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3530 res_limb = zig_and_u16(lhs_limb, rhs_limb);
3531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3532
3533 remaining_bytes -= 16 / CHAR_BIT;
3534 byte_offset += 16 / CHAR_BIT;
3535 }
3536
3537 while (remaining_bytes >= 8 / CHAR_BIT) {
3538 uint8_t res_limb;
3539 uint8_t lhs_limb;
3540 uint8_t rhs_limb;
3541
3542 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3543 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3544 res_limb = zig_and_u8(lhs_limb, rhs_limb);
3545 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3546
3547 remaining_bytes -= 8 / CHAR_BIT;
3548 byte_offset += 8 / CHAR_BIT;
3549 }
3550}
3551
3552static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3553 uint8_t *res_bytes = res;
3554 const uint8_t *lhs_bytes = lhs;
3555 const uint8_t *rhs_bytes = rhs;
3556 uint16_t byte_offset = 0;
3557 uint16_t remaining_bytes = zig_int_bytes(bits);
3558 (void)is_signed;
3559
3560 while (remaining_bytes >= 128 / CHAR_BIT) {
3561 zig_u128 res_limb;
3562 zig_u128 lhs_limb;
3563 zig_u128 rhs_limb;
3564
3565 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3566 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3567 res_limb = zig_or_u128(lhs_limb, rhs_limb);
3568 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3569
3570 remaining_bytes -= 128 / CHAR_BIT;
3571 byte_offset += 128 / CHAR_BIT;
3572 }
3573
3574 while (remaining_bytes >= 64 / CHAR_BIT) {
3575 uint64_t res_limb;
3576 uint64_t lhs_limb;
3577 uint64_t rhs_limb;
3578
3579 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3580 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3581 res_limb = zig_or_u64(lhs_limb, rhs_limb);
3582 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3583
3584 remaining_bytes -= 64 / CHAR_BIT;
3585 byte_offset += 64 / CHAR_BIT;
3586 }
3587
3588 while (remaining_bytes >= 32 / CHAR_BIT) {
3589 uint32_t res_limb;
3590 uint32_t lhs_limb;
3591 uint32_t rhs_limb;
3592
3593 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3594 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3595 res_limb = zig_or_u32(lhs_limb, rhs_limb);
3596 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3597
3598 remaining_bytes -= 32 / CHAR_BIT;
3599 byte_offset += 32 / CHAR_BIT;
3600 }
3601
3602 while (remaining_bytes >= 16 / CHAR_BIT) {
3603 uint16_t res_limb;
3604 uint16_t lhs_limb;
3605 uint16_t rhs_limb;
3606
3607 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
3608 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
3609 res_limb = zig_or_u16(lhs_limb, rhs_limb);
3610 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3611
3612 remaining_bytes -= 16 / CHAR_BIT;
3613 byte_offset += 16 / CHAR_BIT;
3614 }
27243615
27253616 while (remaining_bytes >= 8 / CHAR_BIT) {
27263617 uint8_t res_limb;
......@@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool
28163707 }
28173708}
28183709
3710static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) {
3711 uint8_t *res_bytes = res;
3712 uint16_t byte_offset = 0;
3713 uint16_t remaining_bytes = zig_int_bytes(bits);
3714 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3715
3716#if zig_big_endian
3717 byte_offset = remaining_bytes;
3718#endif
3719
3720 while (remaining_bytes >= 128 / CHAR_BIT) {
3721 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3722
3723#if zig_big_endian
3724 byte_offset -= 128 / CHAR_BIT;
3725#endif
3726
3727 {
3728 zig_u128 res_limb;
3729 bool limb_overflow;
3730
3731 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3732 limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3733 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3734 if (!limb_overflow) return;
3735 }
3736
3737 remaining_bytes -= 128 / CHAR_BIT;
3738
3739#if zig_little_endian
3740 byte_offset += 128 / CHAR_BIT;
3741#endif
3742 }
3743
3744 while (remaining_bytes >= 64 / CHAR_BIT) {
3745 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3746
3747#if zig_big_endian
3748 byte_offset -= 64 / CHAR_BIT;
3749#endif
3750
3751 {
3752 uint64_t res_limb;
3753 bool limb_overflow;
3754
3755 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3756 limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3757 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3758 if (!limb_overflow) return;
3759 }
3760
3761 remaining_bytes -= 64 / CHAR_BIT;
3762
3763#if zig_little_endian
3764 byte_offset += 64 / CHAR_BIT;
3765#endif
3766 }
3767
3768 while (remaining_bytes >= 32 / CHAR_BIT) {
3769 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3770
3771#if zig_big_endian
3772 byte_offset -= 32 / CHAR_BIT;
3773#endif
3774
3775 {
3776 uint32_t res_limb;
3777 bool limb_overflow;
3778
3779 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3780 limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3781 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3782 if (!limb_overflow) return;
3783 }
3784
3785 remaining_bytes -= 32 / CHAR_BIT;
3786
3787#if zig_little_endian
3788 byte_offset += 32 / CHAR_BIT;
3789#endif
3790 }
3791
3792 while (remaining_bytes >= 16 / CHAR_BIT) {
3793 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3794
3795#if zig_big_endian
3796 byte_offset -= 16 / CHAR_BIT;
3797#endif
3798
3799 {
3800 uint16_t res_limb;
3801 bool limb_overflow;
3802
3803 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3804 limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3805 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3806 if (!limb_overflow) return;
3807 }
3808
3809 remaining_bytes -= 16 / CHAR_BIT;
3810
3811#if zig_little_endian
3812 byte_offset += 16 / CHAR_BIT;
3813#endif
3814 }
3815
3816 while (remaining_bytes >= 8 / CHAR_BIT) {
3817 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3818
3819#if zig_big_endian
3820 byte_offset -= 8 / CHAR_BIT;
3821#endif
3822
3823 {
3824 uint8_t res_limb;
3825 bool limb_overflow;
3826
3827 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3828 limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3829 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3830 if (!limb_overflow) return;
3831 }
3832
3833 remaining_bytes -= 8 / CHAR_BIT;
3834
3835#if zig_little_endian
3836 byte_offset += 8 / CHAR_BIT;
3837#endif
3838 }
3839}
3840
3841static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) {
3842 uint8_t *res_bytes = res;
3843 uint16_t byte_offset = 0;
3844 uint16_t remaining_bytes = zig_int_bytes(bits);
3845 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3846
3847#if zig_big_endian
3848 byte_offset = remaining_bytes;
3849#endif
3850
3851 while (remaining_bytes >= 128 / CHAR_BIT) {
3852 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3853
3854#if zig_big_endian
3855 byte_offset -= 128 / CHAR_BIT;
3856#endif
3857
3858 {
3859 zig_u128 res_limb;
3860 bool limb_overflow;
3861
3862 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3863 limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits);
3864 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3865 if (!limb_overflow) return;
3866 }
3867
3868 remaining_bytes -= 128 / CHAR_BIT;
3869
3870#if zig_little_endian
3871 byte_offset += 128 / CHAR_BIT;
3872#endif
3873 }
3874
3875 while (remaining_bytes >= 64 / CHAR_BIT) {
3876 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
3877
3878#if zig_big_endian
3879 byte_offset -= 64 / CHAR_BIT;
3880#endif
3881
3882 {
3883 uint64_t res_limb;
3884 bool limb_overflow;
3885
3886 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3887 limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits);
3888 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3889 if (!limb_overflow) return;
3890 }
3891
3892 remaining_bytes -= 64 / CHAR_BIT;
3893
3894#if zig_little_endian
3895 byte_offset += 64 / CHAR_BIT;
3896#endif
3897 }
3898
3899 while (remaining_bytes >= 32 / CHAR_BIT) {
3900 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
3901
3902#if zig_big_endian
3903 byte_offset -= 32 / CHAR_BIT;
3904#endif
3905
3906 {
3907 uint32_t res_limb;
3908 bool limb_overflow;
3909
3910 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3911 limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits);
3912 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3913 if (!limb_overflow) return;
3914 }
3915
3916 remaining_bytes -= 32 / CHAR_BIT;
3917
3918#if zig_little_endian
3919 byte_offset += 32 / CHAR_BIT;
3920#endif
3921 }
3922
3923 while (remaining_bytes >= 16 / CHAR_BIT) {
3924 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
3925
3926#if zig_big_endian
3927 byte_offset -= 16 / CHAR_BIT;
3928#endif
3929
3930 {
3931 uint16_t res_limb;
3932 bool limb_overflow;
3933
3934 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3935 limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits);
3936 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3937 if (!limb_overflow) return;
3938 }
3939
3940 remaining_bytes -= 16 / CHAR_BIT;
3941
3942#if zig_little_endian
3943 byte_offset += 16 / CHAR_BIT;
3944#endif
3945 }
3946
3947 while (remaining_bytes >= 8 / CHAR_BIT) {
3948 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
3949
3950#if zig_big_endian
3951 byte_offset -= 8 / CHAR_BIT;
3952#endif
3953
3954 {
3955 uint8_t res_limb;
3956 bool limb_overflow;
3957
3958 memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb));
3959 limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits);
3960 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
3961 if (!limb_overflow) return;
3962 }
3963
3964 remaining_bytes -= 8 / CHAR_BIT;
3965
3966#if zig_little_endian
3967 byte_offset += 8 / CHAR_BIT;
3968#endif
3969 }
3970}
3971
3972static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
3973 uint8_t *res_bytes = res;
3974 const uint8_t *arg_bytes = arg;
3975 uint16_t byte_offset = 0;
3976 uint16_t remaining_bytes = zig_int_bytes(bits);
3977 if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) {
3978 memcpy(res, arg, remaining_bytes);
3979 return;
3980 }
3981 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
3982 bool overflow = true;
3983
3984#if zig_big_endian
3985 byte_offset = remaining_bytes;
3986#endif
3987
3988 while (remaining_bytes >= 128 / CHAR_BIT) {
3989 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
3990
3991#if zig_big_endian
3992 byte_offset -= 128 / CHAR_BIT;
3993#endif
3994
3995 {
3996 zig_u128 res_limb;
3997 zig_u128 arg_limb;
3998
3999 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4000 overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
4001 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4002 }
4003
4004 remaining_bytes -= 128 / CHAR_BIT;
4005
4006#if zig_little_endian
4007 byte_offset += 128 / CHAR_BIT;
4008#endif
4009 }
4010
4011 while (remaining_bytes >= 64 / CHAR_BIT) {
4012 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
4013
4014#if zig_big_endian
4015 byte_offset -= 64 / CHAR_BIT;
4016#endif
4017
4018 {
4019 uint64_t res_limb;
4020 uint64_t arg_limb;
4021
4022 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4023 overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
4024 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4025 }
4026
4027 remaining_bytes -= 64 / CHAR_BIT;
4028
4029#if zig_little_endian
4030 byte_offset += 64 / CHAR_BIT;
4031#endif
4032 }
4033
4034 while (remaining_bytes >= 32 / CHAR_BIT) {
4035 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
4036
4037#if zig_big_endian
4038 byte_offset -= 32 / CHAR_BIT;
4039#endif
4040
4041 {
4042 uint32_t res_limb;
4043 uint32_t arg_limb;
4044
4045 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4046 overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
4047 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4048 }
4049
4050 remaining_bytes -= 32 / CHAR_BIT;
4051
4052#if zig_little_endian
4053 byte_offset += 32 / CHAR_BIT;
4054#endif
4055 }
4056
4057 while (remaining_bytes >= 16 / CHAR_BIT) {
4058 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
4059
4060#if zig_big_endian
4061 byte_offset -= 16 / CHAR_BIT;
4062#endif
4063
4064 {
4065 uint16_t res_limb;
4066 uint16_t arg_limb;
4067
4068 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4069 overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
4070 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4071 }
4072
4073 remaining_bytes -= 16 / CHAR_BIT;
4074
4075#if zig_little_endian
4076 byte_offset += 16 / CHAR_BIT;
4077#endif
4078 }
4079
4080 while (remaining_bytes >= 8 / CHAR_BIT) {
4081 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
4082
4083#if zig_big_endian
4084 byte_offset -= 8 / CHAR_BIT;
4085#endif
4086
4087 {
4088 uint8_t res_limb;
4089 uint8_t arg_limb;
4090
4091 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
4092 overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
4093 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
4094 }
4095
4096 remaining_bytes -= 8 / CHAR_BIT;
4097
4098#if zig_little_endian
4099 byte_offset += 8 / CHAR_BIT;
4100#endif
4101 }
4102}
4103
4104static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4105 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4106}
4107
4108static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4109 memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits));
4110}
4111
28194112static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
28204113 uint8_t *res_bytes = res;
28214114 const uint8_t *lhs_bytes = lhs;
28224115 const uint8_t *rhs_bytes = rhs;
28234116 uint16_t byte_offset = 0;
28244117 uint16_t remaining_bytes = zig_int_bytes(bits);
2825 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4118 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
28264119 bool overflow = false;
28274120
28284121#if zig_big_endian
......@@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
30384331 const uint8_t *rhs_bytes = rhs;
30394332 uint16_t byte_offset = 0;
30404333 uint16_t remaining_bytes = zig_int_bytes(bits);
3041 uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
4334 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
30424335 bool overflow = false;
30434336
30444337#if zig_big_endian
......@@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
32384531 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
32394532 }
32404533
3241 remaining_bytes -= 8 / CHAR_BIT;
4534 remaining_bytes -= 8 / CHAR_BIT;
4535
4536#if zig_little_endian
4537 byte_offset += 8 / CHAR_BIT;
4538#endif
4539 }
4540
4541 return overflow;
4542}
4543
4544static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4545 if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4546}
4547
4548static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4549 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
4550}
4551
4552static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4553 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits);
4554
4555 if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return;
4556 switch (sat_sign) {
4557 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4558 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4559 }
4560}
4561
4562static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4563 if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4564}
4565
4566static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4567 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
4568}
4569
4570static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4571 int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1);
4572
4573 if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return;
4574 switch (sat_sign) {
4575 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4576 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4577 }
4578}
4579
4580static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4581 uint8_t *res_bytes = res;
4582 const uint8_t *lhs_bytes = lhs;
4583 const uint8_t *rhs_bytes = rhs;
4584 uint16_t size = zig_int_bytes(bits);
4585 uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4586 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4587 uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8));
4588 uint16_t lhs_byte_offset = sign_byte_offset;
4589 uint16_t lhs_end_byte_offset = UINT16_C(0);
4590 bool overflow = false;
4591
4592#if zig_big_endian
4593 lhs_byte_offset = size - lhs_byte_offset;
4594 lhs_end_byte_offset = size - lhs_end_byte_offset;
4595#endif
4596
4597 while (lhs_byte_offset != lhs_end_byte_offset) {
4598 uint16_t rhs_byte_offset = UINT16_C(0);
4599 uint16_t end_byte_offset = sign_byte_offset;
4600 uint16_t res_byte_offset;
4601 uint16_t lhs_byte;
4602 uint8_t res_byte = UINT8_C(0);
4603 uint16_t mul_res = UINT16_C(0);
4604 uint8_t carry = UINT8_C(0);
4605
4606#if zig_little_endian
4607 lhs_byte_offset -= UINT16_C(1);
4608#else
4609 rhs_byte_offset = size - rhs_byte_offset;
4610 end_byte_offset = size - end_byte_offset;
4611#endif
4612
4613 lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill;
4614
4615#if zig_big_endian
4616 lhs_byte_offset += UINT16_C(1);
4617#endif
4618
4619 res_byte_offset = lhs_byte_offset;
4620
4621 while (res_byte_offset != end_byte_offset) {
4622 bool res_byte_initialized = res_byte_offset != lhs_byte_offset;
4623
4624#if zig_big_endian
4625 rhs_byte_offset -= UINT16_C(1);
4626 res_byte_offset -= UINT16_C(1);
4627#endif
4628
4629 if (res_byte_initialized) res_byte = res_bytes[res_byte_offset];
4630 carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8));
4631 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16(
4632 zig_shr_u16(mul_res, UINT8_C(8))
4633 ), UINT8_C(8));
4634 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4635 carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16(
4636 mul_res,
4637 UINT8_C(8)
4638 ), UINT8_C(8));
4639
4640#if zig_little_endian
4641 rhs_byte_offset += UINT16_C(1);
4642 res_byte_offset += UINT16_C(1);
4643#endif
4644 }
4645
4646 while (rhs_byte_offset != end_byte_offset) {
4647#if zig_big_endian
4648 rhs_byte_offset -= UINT16_C(1);
4649#endif
4650
4651 carry = zig_addo_u8(
4652 &res_byte,
4653 zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))),
4654 carry,
4655 UINT8_C(8)
4656 );
4657 mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill);
4658 carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16(
4659 mul_res,
4660 UINT8_C(8)
4661 ), UINT8_C(8));
4662 overflow |= res_byte != UINT8_C(0);
4663
4664#if zig_little_endian
4665 rhs_byte_offset += UINT16_C(1);
4666#endif
4667 }
4668
4669 overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0);
4670 overflow |= carry != UINT8_C(0);
4671 }
4672
4673#if zig_little_endian
4674 sign_byte_offset -= UINT64_C(1);
4675#else
4676 sign_byte_offset = size - sign_byte_offset;
4677#endif
4678
4679 if (lhs_sign_fill != rhs_sign_fill) {
4680 uint16_t byte_offset = UINT16_C(0);
4681 uint16_t end_byte_offset = sign_byte_offset;
4682 uint8_t res_byte;
4683 int8_t signed_res_byte;
4684 uint8_t carry = UINT8_C(0);
4685
4686#if zig_big_endian
4687 byte_offset = size - byte_offset;
4688 end_byte_offset += UINT16_C(1);
4689#endif
4690
4691 while (byte_offset != end_byte_offset) {
4692#if zig_big_endian
4693 byte_offset -= UINT16_C(1);
4694#endif
4695
4696 carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8));
4697 carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8));
4698 carry += zig_subo_u8(
4699 &res_bytes[byte_offset],
4700 res_byte,
4701 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4702 UINT8_C(8)
4703 );
4704
4705#if zig_little_endian
4706 byte_offset += UINT16_C(1);
4707#endif
4708 }
4709
4710#if zig_big_endian
4711 byte_offset -= UINT16_C(1);
4712#endif
4713
4714 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4715 overflow |= signed_res_byte < INT8_C(0);
4716 overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8));
4717 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4718 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4719 (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset],
4720 UINT8_C(8)
4721 ), UINT8_C(8));
4722 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4723 } else if (lhs_sign_fill != UINT8_C(0)) {
4724 uint16_t byte_offset = UINT16_C(0);
4725 uint16_t end_byte_offset = sign_byte_offset;
4726 uint8_t res_byte;
4727 int8_t signed_res_byte;
4728 uint8_t carry = UINT8_C(1);
4729
4730#if zig_big_endian
4731 byte_offset = size - byte_offset;
4732 end_byte_offset += UINT16_C(1);
4733#endif
4734
4735 while (byte_offset != end_byte_offset) {
4736#if zig_big_endian
4737 byte_offset -= UINT16_C(1);
4738#endif
4739
4740 carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8));
4741 carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8));
4742 carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8));
4743
4744#if zig_little_endian
4745 byte_offset += UINT16_C(1);
4746#endif
4747 }
4748
4749#if zig_big_endian
4750 byte_offset -= UINT16_C(1);
4751#endif
4752
4753 signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8));
4754 overflow |= signed_res_byte < INT8_C(0);
4755 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8));
4756 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4757 lhs_bytes[byte_offset],
4758 UINT8_C(8)
4759 ), UINT8_C(8));
4760 overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8(
4761 rhs_bytes[byte_offset],
4762 UINT8_C(8)
4763 ), UINT8_C(8));
4764 res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8));
4765 } else if (is_signed) {
4766 int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4767
4768 overflow |= signed_res_byte < INT8_C(0);
4769 }
4770
4771 {
4772 uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4773 uint8_t fill_byte = UINT8_C(0);
4774
4775 if (is_signed) {
4776 int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8));
4777 int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits);
4778
4779 overflow |= sign_byte != truncated;
4780 res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
4781 fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
4782 } else {
4783 uint8_t sign_byte = res_bytes[sign_byte_offset];
4784 uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits);
4785
4786 overflow |= sign_byte != truncated;
4787 res_bytes[sign_byte_offset] = truncated;
4788 }
4789
4790#if zig_little_endian
4791 sign_byte_offset += UINT16_C(1);
4792 memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset);
4793#else
4794 memset(&res_bytes[0], fill_byte, sign_byte_offset);
4795#endif
4796 }
4797
4798 return overflow;
4799}
4800
4801static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4802 if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow
4803}
4804
4805static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4806 (void)zig_mulo_big(res, lhs, rhs, is_signed, bits);
4807}
4808
4809static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
4810 int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits);
4811
4812 if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return;
4813 switch (sat_sign) {
4814 case -INT8_C(1): return zig_minInt_big(res, is_signed, bits);
4815 case INT8_C(0): return zig_maxInt_big(res, is_signed, bits);
4816 }
4817}
4818
4819static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4820 if (is_signed) {
4821 zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4822 __divei5(res, lhs, rhs, temp, bits);
4823 } else {
4824 zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4825 __udivei5(res, lhs, rhs, temp, bits);
4826 }
4827}
4828
4829static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4830 if (is_signed) {
4831 zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4832 __modei5(res, lhs, rhs, temp, bits);
4833 } else {
4834 zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits);
4835 __umodei5(res, lhs, rhs, temp, bits);
4836 }
4837}
4838
4839static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4840 bool decrement = false;
4841
4842 if (is_signed) {
4843 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4844 decrement = zig_u32_bitCast_i32(zig_xor_i32(
4845 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4846 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4847 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32));
4848 }
4849 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4850 if (decrement) zig_decrement_big(res, is_signed, bits);
4851}
4852
4853static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4854 bool increment = false;
4855
4856 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4857 increment = zig_xor_i32(
4858 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4859 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4860 ) > INT32_C(0);
4861 zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits);
4862 if (increment) zig_increment_big(res, is_signed, bits);
4863}
4864
4865static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) {
4866 bool fixup = false;
4867
4868 zig_rem_big(res, lhs, rhs, temp, is_signed, bits);
4869 if (is_signed && zig_u32_bitCast_i32(zig_xor_i32(
4870 zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits),
4871 zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32)
4872 ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits);
4873}
4874
4875static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4876 uint8_t *res_bytes = res;
4877 const uint8_t *lhs_bytes = lhs;
4878 uint16_t size = zig_int_bytes(bits);
4879 uint16_t res_byte_offset = UINT16_C(0);
4880 uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3));
4881 uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4882 uint8_t lhs_prev_byte;
4883 uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3));
4884
4885#if zig_big_endian
4886 res_byte_offset = size - res_byte_offset;
4887 lhs_byte_offset = size - lhs_byte_offset;
4888 end_byte_offset = size - end_byte_offset;
4889#endif
4890
4891 {
4892#if zig_big_endian
4893 lhs_byte_offset -= UINT16_C(1);
4894#endif
4895
4896 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4897
4898#if zig_little_endian
4899 lhs_byte_offset += UINT16_C(1);
4900#endif
4901 }
4902
4903 while (lhs_byte_offset != end_byte_offset) {
4904#if zig_big_endian
4905 res_byte_offset -= UINT16_C(1);
4906 lhs_byte_offset -= UINT16_C(1);
4907#endif
4908
4909 {
4910 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
4911
4912 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
4913 zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)),
4914 zig_u16_intCast_u8(lhs_prev_byte)
4915 ), byte_shift));
4916 lhs_prev_byte = lhs_byte;
4917 }
4918
4919#if zig_little_endian
4920 res_byte_offset += UINT16_C(1);
4921 lhs_byte_offset += UINT16_C(1);
4922#endif
4923 }
4924
4925 {
4926 uint8_t lhs_sign_fill = UINT8_C(0);
4927
4928#if zig_big_endian
4929 res_byte_offset -= UINT16_C(1);
4930#endif
4931
4932 if (is_signed) {
4933 int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8));
4934
4935 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
4936 lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
4937 } else {
4938 res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift);
4939 }
4940
4941#if zig_little_endian
4942 res_byte_offset += UINT16_C(1);
4943 memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset);
4944#else
4945 memset(&res_bytes[0], lhs_sign_fill, res_byte_offset);
4946#endif
4947 }
4948}
4949
4950static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
4951 uint8_t *res_bytes = res;
4952 const uint8_t *lhs_bytes = lhs;
4953 uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8));
4954 uint16_t size = zig_int_bytes(bits);
4955 uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
4956 uint16_t lhs_byte_offset = UINT16_C(0);
4957 uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3));
4958 uint8_t lhs_prev_byte = lhs_sign_fill;
4959 uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3));
4960 bool overflow = false;
4961
4962#if zig_little_endian
4963 lhs_byte_offset = size - lhs_byte_offset;
4964#else
4965 res_byte_offset = size - res_byte_offset;
4966 end_byte_offset = size - end_byte_offset;
4967#endif
4968
4969 while (lhs_byte_offset != end_byte_offset) {
4970#if zig_little_endian
4971 lhs_byte_offset -= UINT16_C(1);
4972#endif
4973
4974 overflow |= lhs_prev_byte != lhs_sign_fill;
4975 lhs_prev_byte = lhs_bytes[lhs_byte_offset];
4976
4977#if zig_big_endian
4978 lhs_byte_offset += UINT16_C(1);
4979#endif
4980 }
4981
4982#if zig_little_endian
4983 end_byte_offset = UINT16_C(0);
4984#else
4985 end_byte_offset = size;
4986#endif
4987
4988 {
4989 bool lhs_more_bytes = lhs_byte_offset != end_byte_offset;
4990
4991#if zig_little_endian
4992 if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1);
4993#endif
4994
4995 {
4996 uint8_t lhs_byte = UINT8_C(0);
4997
4998 if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset];
4999
5000 if (is_signed) {
5001 int16_t shifted = zig_shr_i16(zig_or_i16(
5002 zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5003 zig_i16_intCast_u8(lhs_byte)
5004 ), byte_shift);
5005 int8_t truncated = zig_i8_truncate_i16(
5006 shifted,
5007 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5008 );
5009 uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8));
5010
5011 overflow |= zig_i16_intCast_i8(truncated) != shifted;
5012#if zig_little_endian
5013 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5014 res_byte_offset -= UINT16_C(1);
5015#else
5016 memset(&res_bytes[0], fill, res_byte_offset);
5017#endif
5018 res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8));
5019 } else {
5020 uint16_t shifted = zig_shr_u16(zig_or_u16(
5021 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5022 zig_u16_intCast_u8(lhs_byte)
5023 ), byte_shift);
5024 uint8_t truncated = zig_u8_truncate_u16(
5025 shifted,
5026 zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1)
5027 );
5028
5029 overflow |= zig_u16_intCast_u8(truncated) != shifted;
5030#if zig_little_endian
5031 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5032 res_byte_offset -= UINT16_C(1);
5033#else
5034 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5035#endif
5036 res_bytes[res_byte_offset] = truncated;
5037 }
5038
5039 lhs_prev_byte = lhs_byte;
5040 }
5041
5042#if zig_big_endian
5043 res_byte_offset += UINT16_C(1);
5044 if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1);
5045#endif
5046 }
5047
5048 while (lhs_byte_offset != end_byte_offset) {
5049#if zig_little_endian
5050 res_byte_offset -= UINT16_C(1);
5051 lhs_byte_offset -= UINT16_C(1);
5052#endif
5053
5054 {
5055 uint8_t lhs_byte = lhs_bytes[lhs_byte_offset];
5056
5057 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5058 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5059 zig_u16_intCast_u8(lhs_byte)
5060 ), byte_shift));
5061 lhs_prev_byte = lhs_byte;
5062 }
5063
5064#if zig_big_endian
5065 res_byte_offset += UINT16_C(1);
5066 lhs_byte_offset += UINT16_C(1);
5067#endif
5068 }
5069
5070 {
5071#if zig_little_endian
5072 res_byte_offset -= UINT16_C(1);
5073#endif
5074
5075 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(
5076 zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)),
5077 byte_shift
5078 ));
5079
5080#if zig_big_endian
5081 res_byte_offset += UINT16_C(1);
5082#endif
5083 }
5084
5085#if zig_little_endian
5086 memset(&res_bytes[0], zig_minInt_u8, res_byte_offset);
5087#else
5088 memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset);
5089#endif
5090
5091 return overflow;
5092}
5093
5094static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5095 if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits
5096}
5097
5098static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) {
5099 (void)zig_shlo_big(res, lhs, rhs, is_signed, bits);
5100}
5101
5102#define zig_big_shls_builtin(w) \
5103 static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \
5104 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5105 uint##w##_t res; \
5106 const uint8_t *rhs_bytes = rhs; \
5107 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5108 !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5109 return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \
5110 } \
5111\
5112 static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \
5113 uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \
5114 int##w##_t res; \
5115 const uint8_t *rhs_bytes = rhs; \
5116 if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \
5117 !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \
5118 return lhs == INT##w##_C(0) ? INT##w##_C(0) : \
5119 lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \
5120 } \
5121\
5122 static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \
5123 const uint8_t *lhs_bytes = lhs; \
5124 if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \
5125 switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \
5126 case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \
5127 case INT32_C(0): return zig_minInt_big(res, false, bits); \
5128 case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \
5129 default: zig_unreachable(); \
5130 } \
5131 }
5132zig_big_shls_builtin(8)
5133zig_big_shls_builtin(16)
5134zig_big_shls_builtin(32)
5135zig_big_shls_builtin(64)
5136
5137static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5138 uint8_t *res_bytes = res;
5139 const uint8_t *arg_bytes = arg;
5140 uint16_t res_byte_offset = UINT16_C(0);
5141 uint16_t arg_byte_offset = bits / CHAR_BIT;
5142 uint16_t end_byte_offset = UINT16_C(1);
5143 uint16_t size = zig_int_bytes(bits);
5144
5145#if zig_big_endian
5146 res_byte_offset = size - res_byte_offset;
5147 arg_byte_offset = size - arg_byte_offset;
5148 end_byte_offset = size - end_byte_offset;
5149#endif
5150
5151 while (arg_byte_offset != end_byte_offset) {
5152#if zig_little_endian
5153 arg_byte_offset -= UINT16_C(1);
5154#else
5155 res_byte_offset -= UINT16_C(1);
5156#endif
5157
5158 res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset];
32425159
32435160#if zig_little_endian
3244 byte_offset += 8 / CHAR_BIT;
5161 res_byte_offset += UINT16_C(1);
5162#else
5163 arg_byte_offset += UINT16_C(1);
32455164#endif
32465165 }
32475166
3248 return overflow;
3249}
5167 {
5168#if zig_little_endian
5169 arg_byte_offset -= UINT16_C(1);
5170#else
5171 res_byte_offset -= UINT16_C(1);
5172#endif
32505173
3251static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3252 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
3253}
5174 {
5175 uint8_t byte = arg_bytes[arg_byte_offset];
5176 uint8_t fill = is_signed
5177 ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8))
5178 : UINT8_C(0);
32545179
3255static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3256 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
3257}
5180 res_bytes[res_byte_offset] = byte;
32585181
3259zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3260static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3261 if (!is_signed) {
3262 __udivei4(res, lhs, rhs, bits);
3263 return;
5182#if zig_little_endian
5183 res_byte_offset += UINT16_C(1);
5184 memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset);
5185#else
5186 memset(&res_bytes[0], fill, res_byte_offset);
5187#endif
5188 }
32645189 }
3265
3266 zig_trap();
32675190}
32685191
3269static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3270 if (!is_signed) {
3271 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
3272 return;
3273 }
5192static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) {
5193 uint8_t *res_bytes = res;
5194 const uint8_t *arg_bytes = arg;
5195 uint16_t size = zig_int_bytes(bits);
5196 uint16_t res_byte_offset = UINT16_C(0);
5197 uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5198 uint16_t end_byte_offset = UINT16_C(0);
5199 uint8_t arg_prev_byte;
5200 uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3)));
32745201
3275 zig_trap();
3276}
5202#if zig_big_endian
5203 res_byte_offset = size - res_byte_offset;
5204 arg_byte_offset = size - arg_byte_offset;
5205 end_byte_offset = size - end_byte_offset;
5206#endif
32775207
3278static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3279 zig_trap();
3280}
5208 {
5209#if zig_little_endian
5210 arg_byte_offset -= UINT16_C(1);
5211#endif
32815212
3282zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
3283static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3284 if (!is_signed) {
3285 __umodei4(res, lhs, rhs, bits);
3286 return;
5213 arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5214
5215#if zig_big_endian
5216 arg_byte_offset += UINT16_C(1);
5217#endif
32875218 }
32885219
3289 zig_trap();
3290}
5220 while (arg_byte_offset != end_byte_offset) {
5221#if zig_big_endian
5222 res_byte_offset -= UINT16_C(1);
5223#else
5224 arg_byte_offset -= UINT16_C(1);
5225#endif
32915226
3292static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
3293 if (!is_signed) {
3294 zig_rem_big(res, lhs, rhs, is_signed, bits);
3295 return;
5227 {
5228 uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8));
5229
5230 res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16(
5231 zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)),
5232 zig_u16_intCast_u8(arg_prev_byte)
5233 ), byte_shift));
5234 arg_prev_byte = arg_byte;
5235 }
5236
5237#if zig_little_endian
5238 res_byte_offset += UINT16_C(1);
5239#else
5240 arg_byte_offset += UINT16_C(1);
5241#endif
32965242 }
32975243
3298 zig_trap();
5244 {
5245 uint8_t arg_sign_fill = UINT8_C(0);
5246
5247#if zig_big_endian
5248 res_byte_offset -= UINT16_C(1);
5249#endif
5250
5251 if (is_signed) {
5252 int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8));
5253
5254 res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift);
5255 arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8));
5256 } else {
5257 res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift);
5258 }
5259
5260#if zig_little_endian
5261 res_byte_offset += UINT16_C(1);
5262 memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset);
5263#else
5264 memset(&res_bytes[0], arg_sign_fill, res_byte_offset);
5265#endif
5266 }
32995267}
33005268
3301static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
3302 const uint8_t *val_bytes = val;
5269static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) {
5270 const uint8_t *arg_bytes = arg;
33035271 uint16_t byte_offset = 0;
3304 uint16_t remaining_bytes = zig_int_bytes(bits);
3305 uint16_t skip_bits = remaining_bytes * 8 - bits;
3306 uint16_t total_lz = 0;
3307 uint16_t limb_lz;
5272 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5273 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5274 uint16_t total_pc = 0;
33085275 (void)is_signed;
33095276
3310#if zig_little_endian
3311 byte_offset = remaining_bytes;
5277#if zig_big_endian
5278 byte_offset = zig_int_bytes(bits);
33125279#endif
33135280
33145281 while (remaining_bytes >= 128 / CHAR_BIT) {
3315#if zig_little_endian
5282 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5283
5284#if zig_big_endian
33165285 byte_offset -= 128 / CHAR_BIT;
33175286#endif
33185287
33195288 {
3320 zig_u128 val_limb;
5289 zig_u128 arg_limb;
33215290
3322 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3323 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);
5291 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5292 total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
33245293 }
33255294
3326 total_lz += limb_lz;
3327 if (limb_lz < 128 - skip_bits) return total_lz;
3328 skip_bits = 0;
33295295 remaining_bytes -= 128 / CHAR_BIT;
33305296
3331#if zig_big_endian
5297#if zig_little_endian
33325298 byte_offset += 128 / CHAR_BIT;
33335299#endif
33345300 }
33355301
33365302 while (remaining_bytes >= 64 / CHAR_BIT) {
3337#if zig_little_endian
5303 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5304
5305#if zig_big_endian
33385306 byte_offset -= 64 / CHAR_BIT;
33395307#endif
33405308
33415309 {
3342 uint64_t val_limb;
5310 uint64_t arg_limb;
33435311
3344 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3345 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);
5312 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5313 total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
33465314 }
33475315
3348 total_lz += limb_lz;
3349 if (limb_lz < 64 - skip_bits) return total_lz;
3350 skip_bits = 0;
33515316 remaining_bytes -= 64 / CHAR_BIT;
33525317
3353#if zig_big_endian
5318#if zig_little_endian
33545319 byte_offset += 64 / CHAR_BIT;
33555320#endif
33565321 }
33575322
33585323 while (remaining_bytes >= 32 / CHAR_BIT) {
3359#if zig_little_endian
5324 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5325
5326#if zig_big_endian
33605327 byte_offset -= 32 / CHAR_BIT;
33615328#endif
33625329
33635330 {
3364 uint32_t val_limb;
5331 uint32_t arg_limb;
33655332
3366 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3367 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);
5333 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5334 total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
33685335 }
33695336
3370 total_lz += limb_lz;
3371 if (limb_lz < 32 - skip_bits) return total_lz;
3372 skip_bits = 0;
33735337 remaining_bytes -= 32 / CHAR_BIT;
33745338
3375#if zig_big_endian
5339#if zig_little_endian
33765340 byte_offset += 32 / CHAR_BIT;
33775341#endif
33785342 }
33795343
33805344 while (remaining_bytes >= 16 / CHAR_BIT) {
3381#if zig_little_endian
5345 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5346
5347#if zig_big_endian
33825348 byte_offset -= 16 / CHAR_BIT;
33835349#endif
33845350
33855351 {
3386 uint16_t val_limb;
5352 uint16_t arg_limb;
33875353
3388 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3389 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);
5354 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5355 total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
33905356 }
33915357
3392 total_lz += limb_lz;
3393 if (limb_lz < 16 - skip_bits) return total_lz;
3394 skip_bits = 0;
33955358 remaining_bytes -= 16 / CHAR_BIT;
33965359
3397#if zig_big_endian
5360#if zig_little_endian
33985361 byte_offset += 16 / CHAR_BIT;
33995362#endif
34005363 }
34015364
34025365 while (remaining_bytes >= 8 / CHAR_BIT) {
3403#if zig_little_endian
5366 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5367
5368#if zig_big_endian
34045369 byte_offset -= 8 / CHAR_BIT;
34055370#endif
34065371
34075372 {
3408 uint8_t val_limb;
5373 uint8_t arg_limb;
34095374
3410 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3411 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);
5375 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5376 total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
34125377 }
34135378
3414 total_lz += limb_lz;
3415 if (limb_lz < 8 - skip_bits) return total_lz;
3416 skip_bits = 0;
34175379 remaining_bytes -= 8 / CHAR_BIT;
34185380
3419#if zig_big_endian
5381#if zig_little_endian
34205382 byte_offset += 8 / CHAR_BIT;
34215383#endif
34225384 }
34235385
3424 return total_lz;
5386 return total_pc;
34255387}
34265388
3427static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {
3428 const uint8_t *val_bytes = val;
3429 uint16_t byte_offset = 0;
3430 uint16_t remaining_bytes = zig_int_bytes(bits);
3431 uint16_t total_tz = 0;
5389static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) {
5390 const uint8_t *arg_bytes = arg;
5391 uint16_t byte_offset = UINT16_C(0);
5392 uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5393 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5394 uint16_t total_tz = UINT16_C(0);
34325395 uint16_t limb_tz;
34335396 (void)is_signed;
34345397
34355398#if zig_big_endian
3436 byte_offset = remaining_bytes;
5399 byte_offset = zig_int_bytes(bits);
34375400#endif
34385401
34395402 while (remaining_bytes >= 128 / CHAR_BIT) {
5403 uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
5404
34405405#if zig_big_endian
34415406 byte_offset -= 128 / CHAR_BIT;
34425407#endif
34435408
34445409 {
3445 zig_u128 val_limb;
5410 zig_u128 arg_limb;
34465411
3447 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3448 limb_tz = zig_ctz_u128(val_limb, 128);
5412 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5413 limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
34495414 }
34505415
34515416 total_tz += limb_tz;
3452 if (limb_tz < 128) return total_tz;
5417 if (limb_tz < limb_bits) return total_tz;
34535418 remaining_bytes -= 128 / CHAR_BIT;
34545419
34555420#if zig_little_endian
......@@ -3458,19 +5423,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34585423 }
34595424
34605425 while (remaining_bytes >= 64 / CHAR_BIT) {
5426 uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
5427
34615428#if zig_big_endian
34625429 byte_offset -= 64 / CHAR_BIT;
34635430#endif
34645431
34655432 {
3466 uint64_t val_limb;
5433 uint64_t arg_limb;
34675434
3468 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3469 limb_tz = zig_ctz_u64(val_limb, 64);
5435 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5436 limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
34705437 }
34715438
34725439 total_tz += limb_tz;
3473 if (limb_tz < 64) return total_tz;
5440 if (limb_tz < limb_bits) return total_tz;
34745441 remaining_bytes -= 64 / CHAR_BIT;
34755442
34765443#if zig_little_endian
......@@ -3479,19 +5446,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
34795446 }
34805447
34815448 while (remaining_bytes >= 32 / CHAR_BIT) {
5449 uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
5450
34825451#if zig_big_endian
34835452 byte_offset -= 32 / CHAR_BIT;
34845453#endif
34855454
34865455 {
3487 uint32_t val_limb;
5456 uint32_t arg_limb;
34885457
3489 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3490 limb_tz = zig_ctz_u32(val_limb, 32);
5458 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5459 limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
34915460 }
34925461
34935462 total_tz += limb_tz;
3494 if (limb_tz < 32) return total_tz;
5463 if (limb_tz < limb_bits) return total_tz;
34955464 remaining_bytes -= 32 / CHAR_BIT;
34965465
34975466#if zig_little_endian
......@@ -3500,19 +5469,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35005469 }
35015470
35025471 while (remaining_bytes >= 16 / CHAR_BIT) {
5472 uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
5473
35035474#if zig_big_endian
35045475 byte_offset -= 16 / CHAR_BIT;
35055476#endif
35065477
35075478 {
3508 uint16_t val_limb;
5479 uint16_t arg_limb;
35095480
3510 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3511 limb_tz = zig_ctz_u16(val_limb, 16);
5481 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5482 limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
35125483 }
35135484
35145485 total_tz += limb_tz;
3515 if (limb_tz < 16) return total_tz;
5486 if (limb_tz < limb_bits) return total_tz;
35165487 remaining_bytes -= 16 / CHAR_BIT;
35175488
35185489#if zig_little_endian
......@@ -3521,19 +5492,21 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35215492 }
35225493
35235494 while (remaining_bytes >= 8 / CHAR_BIT) {
5495 uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
5496
35245497#if zig_big_endian
35255498 byte_offset -= 8 / CHAR_BIT;
35265499#endif
35275500
35285501 {
3529 uint8_t val_limb;
5502 uint8_t arg_limb;
35305503
3531 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3532 limb_tz = zig_ctz_u8(val_limb, 8);
5504 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5505 limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
35335506 }
35345507
35355508 total_tz += limb_tz;
3536 if (limb_tz < 8) return total_tz;
5509 if (limb_tz < limb_bits) return total_tz;
35375510 remaining_bytes -= 8 / CHAR_BIT;
35385511
35395512#if zig_little_endian
......@@ -3544,113 +5517,141 @@ static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bit
35445517 return total_tz;
35455518}
35465519
3547static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {
3548 const uint8_t *val_bytes = val;
3549 uint16_t byte_offset = 0;
3550 uint16_t remaining_bytes = zig_int_bytes(bits);
3551 uint16_t total_pc = 0;
5520static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) {
5521 const uint8_t *arg_bytes = arg;
5522 uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1);
5523 uint16_t remaining_bytes = byte_offset;
5524 uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits);
5525 bool sign_limb = true;
5526 uint16_t total_lz = UINT16_C(0);
5527 uint16_t limb_lz;
35525528 (void)is_signed;
35535529
35545530#if zig_big_endian
3555 byte_offset = remaining_bytes;
5531 byte_offset = zig_int_bytes(bits) - remaining_bytes;
35565532#endif
35575533
35585534 while (remaining_bytes >= 128 / CHAR_BIT) {
3559#if zig_big_endian
5535 uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0));
5536
5537#if zig_little_endian
35605538 byte_offset -= 128 / CHAR_BIT;
35615539#endif
35625540
35635541 {
3564 zig_u128 val_limb;
5542 zig_u128 arg_limb;
35655543
3566 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3567 total_pc += zig_popcount_u128(val_limb, 128);
5544 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5545 limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits);
35685546 }
35695547
5548 total_lz += limb_lz;
5549 if (limb_lz < limb_bits) return total_lz;
5550 sign_limb = false;
35705551 remaining_bytes -= 128 / CHAR_BIT;
35715552
3572#if zig_little_endian
5553#if zig_big_endian
35735554 byte_offset += 128 / CHAR_BIT;
35745555#endif
35755556 }
35765557
35775558 while (remaining_bytes >= 64 / CHAR_BIT) {
3578#if zig_big_endian
5559 uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0));
5560
5561#if zig_little_endian
35795562 byte_offset -= 64 / CHAR_BIT;
35805563#endif
35815564
35825565 {
3583 uint64_t val_limb;
5566 uint64_t arg_limb;
35845567
3585 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3586 total_pc += zig_popcount_u64(val_limb, 64);
5568 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5569 limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits);
35875570 }
35885571
5572 total_lz += limb_lz;
5573 if (limb_lz < limb_bits) return total_lz;
5574 sign_limb = false;
35895575 remaining_bytes -= 64 / CHAR_BIT;
35905576
3591#if zig_little_endian
5577#if zig_big_endian
35925578 byte_offset += 64 / CHAR_BIT;
35935579#endif
35945580 }
35955581
35965582 while (remaining_bytes >= 32 / CHAR_BIT) {
3597#if zig_big_endian
5583 uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0));
5584
5585#if zig_little_endian
35985586 byte_offset -= 32 / CHAR_BIT;
35995587#endif
36005588
36015589 {
3602 uint32_t val_limb;
5590 uint32_t arg_limb;
36035591
3604 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3605 total_pc += zig_popcount_u32(val_limb, 32);
5592 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5593 limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits);
36065594 }
36075595
5596 total_lz += limb_lz;
5597 if (limb_lz < limb_bits) return total_lz;
5598 sign_limb = false;
36085599 remaining_bytes -= 32 / CHAR_BIT;
36095600
3610#if zig_little_endian
5601#if zig_big_endian
36115602 byte_offset += 32 / CHAR_BIT;
36125603#endif
36135604 }
36145605
36155606 while (remaining_bytes >= 16 / CHAR_BIT) {
3616#if zig_big_endian
5607 uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0));
5608
5609#if zig_little_endian
36175610 byte_offset -= 16 / CHAR_BIT;
36185611#endif
36195612
36205613 {
3621 uint16_t val_limb;
5614 uint16_t arg_limb;
36225615
3623 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3624 total_pc = zig_popcount_u16(val_limb, 16);
5616 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5617 limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits);
36255618 }
36265619
5620 total_lz += limb_lz;
5621 if (limb_lz < limb_bits) return total_lz;
5622 sign_limb = false;
36275623 remaining_bytes -= 16 / CHAR_BIT;
36285624
3629#if zig_little_endian
5625#if zig_big_endian
36305626 byte_offset += 16 / CHAR_BIT;
36315627#endif
36325628 }
36335629
36345630 while (remaining_bytes >= 8 / CHAR_BIT) {
3635#if zig_big_endian
5631 uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0));
5632
5633#if zig_little_endian
36365634 byte_offset -= 8 / CHAR_BIT;
36375635#endif
36385636
36395637 {
3640 uint8_t val_limb;
5638 uint8_t arg_limb;
36415639
3642 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
3643 total_pc = zig_popcount_u8(val_limb, 8);
5640 memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb));
5641 limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits);
36445642 }
36455643
5644 total_lz += limb_lz;
5645 if (limb_lz < limb_bits) return total_lz;
5646 sign_limb = false;
36465647 remaining_bytes -= 8 / CHAR_BIT;
36475648
3648#if zig_little_endian
5649#if zig_big_endian
36495650 byte_offset += 8 / CHAR_BIT;
36505651#endif
36515652 }
36525653
3653 return total_pc;
5654 return total_lz;
36545655}
36555656
36565657/* ========================= Floating Point Support ========================= */
......@@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input);
36875688#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
36885689#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
36895690#else
3690#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)
3691#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)
3692#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)
3693#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)
3694#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)
5691#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr)
5692#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr)
5693#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr)
5694#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr)
5695#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr)
36955696#endif
36965697
36975698#define zig_has_f16 1
36985699#define zig_libc_name_f16(name) __##name##h
36995700#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
3700#if FLT_MANT_DIG == 11
5701#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11
37015702typedef float zig_f16;
37025703#define zig_make_f16(fp, repr) fp##f
3703#elif DBL_MANT_DIG == 11
5704#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11
37045705typedef double zig_f16;
37055706#define zig_make_f16(fp, repr) fp
3706#elif LDBL_MANT_DIG == 11
5707#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11
37075708typedef long double zig_f16;
37085709#define zig_make_f16(fp, repr) fp##l
3709#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
5710#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc))
37105711typedef _Float16 zig_f16;
37115712#define zig_make_f16(fp, repr) fp##f16
3712#elif defined(__SIZEOF_FP16__)
5713#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__)
37135714typedef __fp16 zig_f16;
37145715#define zig_make_f16(fp, repr) fp##f16
37155716#else
......@@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16;
37235724#undef zig_init_special_f16
37245725#define zig_init_special_f16(sign, name, arg, repr) repr
37255726#endif
3726#if defined(zig_darwin) && defined(zig_x86)
3727typedef uint16_t zig_compiler_rt_f16;
3728#else
3729typedef zig_f16 zig_compiler_rt_f16;
3730#endif
37315727
37325728#define zig_has_f32 1
37335729#define zig_libc_name_f32(name) name##f
......@@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16;
37365732#else
37375733#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
37385734#endif
3739#if FLT_MANT_DIG == 24
5735#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24
37405736typedef float zig_f32;
37415737#define zig_make_f32(fp, repr) fp##f
3742#elif DBL_MANT_DIG == 24
5738#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24
37435739typedef double zig_f32;
37445740#define zig_make_f32(fp, repr) fp
3745#elif LDBL_MANT_DIG == 24
5741#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24
37465742typedef long double zig_f32;
37475743#define zig_make_f32(fp, repr) fp##l
3748#elif FLT32_MANT_DIG == 24
5744#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24
37495745typedef _Float32 zig_f32;
37505746#define zig_make_f32(fp, repr) fp##f32
37515747#else
......@@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32;
37685764#else
37695765#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
37705766#endif
3771#if FLT_MANT_DIG == 53
5767#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53
37725768typedef float zig_f64;
37735769#define zig_make_f64(fp, repr) fp##f
3774#elif DBL_MANT_DIG == 53
5770#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53
37755771typedef double zig_f64;
37765772#define zig_make_f64(fp, repr) fp
3777#elif LDBL_MANT_DIG == 53
5773#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53
37785774typedef long double zig_f64;
37795775#define zig_make_f64(fp, repr) fp##l
3780#elif FLT64_MANT_DIG == 53
5776#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53
37815777typedef _Float64 zig_f64;
37825778#define zig_make_f64(fp, repr) fp##f64
3783#elif FLT32X_MANT_DIG == 53
5779#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53
37845780typedef _Float32x zig_f64;
37855781#define zig_make_f64(fp, repr) fp##f32x
37865782#else
......@@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64;
37985794#define zig_has_f80 1
37995795#define zig_libc_name_f80(name) __##name##x
38005796#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
3801#if FLT_MANT_DIG == 64
5797#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI
5798#undef zig_has_f80
5799typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80;
5800#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent }
5801#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5802#define zig_mantissa_repr_f80(arg) (arg).mantissa
5803#define zig_exponent_repr_f80(arg) (arg).exponent
5804#elif FLT_MANT_DIG == 64
38025805typedef float zig_f80;
38035806#define zig_make_f80(fp, repr) fp##f
38045807#elif DBL_MANT_DIG == 64
......@@ -3818,68 +5821,91 @@ typedef __float80 zig_f80;
38185821#define zig_make_f80(fp, repr) fp##l
38195822#else
38205823#undef zig_has_f80
3821#define zig_has_f80 0
3822#define zig_repr_f80 u128
38235824typedef zig_u128 zig_f80;
5825#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa)
5826#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa)
5827#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg)
5828#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg)
5829#endif
5830#ifndef zig_has_f80
5831#define zig_has_f80 0
38245832#define zig_make_f80(fp, repr) repr
5833#ifndef zig_make_repr_f80
5834#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent)
5835#endif
38255836#undef zig_make_special_f80
38265837#define zig_make_special_f80(sign, name, arg, repr) repr
38275838#undef zig_init_special_f80
38285839#define zig_init_special_f80(sign, name, arg, repr) repr
38295840#endif
38305841
3831#if defined(zig_gcc) && defined(zig_x86)
3832#define zig_f128_has_miscompilations 1
3833#else
3834#define zig_f128_has_miscompilations 0
3835#endif
3836
38375842#define zig_has_f128 1
3838#define zig_libc_name_f128(name) name##q
5843#define zig_libc_name_f128(name) name##f128
38395844#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
3840#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113
5845#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI
5846#undef zig_has_f128
5847#if zig_little_endian
5848typedef struct { uint64_t lo, hi; } zig_f128;
5849#else
5850typedef struct { uint64_t hi, lo; } zig_f128;
5851#endif
5852#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }
5853#define zig_lo_repr_f128(arg) (arg).lo
5854#define zig_hi_repr_f128(arg) (arg).hi
5855#elif FLT_MANT_DIG == 113
38415856typedef float zig_f128;
38425857#define zig_make_f128(fp, repr) fp##f
3843#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113
5858#elif DBL_MANT_DIG == 113
38445859typedef double zig_f128;
38455860#define zig_make_f128(fp, repr) fp
3846#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113
5861#elif LDBL_MANT_DIG == 113
38475862typedef long double zig_f128;
38485863#define zig_make_f128(fp, repr) fp##l
3849#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113
5864#elif FLT128_MANT_DIG == 113
38505865typedef _Float128 zig_f128;
38515866#define zig_make_f128(fp, repr) fp##f128
3852#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113
5867#elif FLT64X_MANT_DIG == 113
38535868typedef _Float64x zig_f128;
38545869#define zig_make_f128(fp, repr) fp##f64x
3855#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)
5870#elif defined(__SIZEOF_FLOAT128__)
38565871typedef __float128 zig_f128;
38575872#define zig_make_f128(fp, repr) fp##q
38585873#undef zig_make_special_f128
38595874#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
38605875#else
38615876#undef zig_has_f128
3862#define zig_has_f128 0
3863#undef zig_make_special_f128
3864#undef zig_init_special_f128
3865#if defined(zig_darwin) || defined(zig_aarch64)
3866typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;
3867zig_basic_operator(zig_v2u64, xor_v2u64, ^)
3868#define zig_repr_f128 v2u64
3869typedef zig_v2u64 zig_f128;
3870#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }
3871#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128
3872#define zig_make_f128(fp, repr) zig_make_f128_##repr
3873#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3874#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr
3875#else
3876#define zig_repr_f128 u128
5877#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC)
5878#if defined(zig_msvc) && !defined(__clang__)
5879#include <emmintrin.h>
5880typedef __m128i zig_f128;
5881#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } }
5882#define zig_lo_repr_f128(arg) (arg).m128i_u64[0]
5883#define zig_hi_repr_f128(arg) (arg).m128i_u64[1]
5884#else
5885typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128;
5886#define zig_init_repr_f128(hi, lo) { lo, hi }
5887#define zig_lo_repr_f128(arg) (arg)[0]
5888#define zig_hi_repr_f128(arg) (arg)[1]
5889#endif
5890#else
38775891typedef zig_u128 zig_f128;
5892#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo)
5893#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo)
5894#define zig_lo_repr_f128(arg) zig_lo_u128(arg)
5895#define zig_hi_repr_f128(arg) zig_hi_u128(arg)
5896#endif
5897#endif
5898#ifndef zig_has_f128
5899#define zig_has_f128 0
38785900#define zig_make_f128(fp, repr) repr
5901#ifndef zig_make_repr_f128
5902#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo)
5903#endif
5904#undef zig_make_special_f128
38795905#define zig_make_special_f128(sign, name, arg, repr) repr
5906#undef zig_init_special_f128
38805907#define zig_init_special_f128(sign, name, arg, repr) repr
38815908#endif
3882#endif
38835909
38845910#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
38855911/* Emulate msvc abi on a gnu compiler */
......@@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble;
38925918typedef long double zig_c_longdouble;
38935919#endif
38945920
3895#define zig_bitCast_float(Type, ReprType) \
3896 static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \
3897 zig_##Type result; \
3898 memcpy(&result, &repr, sizeof(result)); \
3899 return result; \
5921#if __AVR__
5922typedef signed char zig_FloatCompareResult;
5923#elif defined(zig_aarch64)
5924typedef signed int zig_FloatCompareResult;
5925#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__
5926typedef signed long zig_FloatCompareResult;
5927#else
5928typedef signed long long zig_FloatCompareResult;
5929#endif
5930
5931#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \
5932 static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \
5933 zig_f##w res; \
5934 memcpy(&res, &arg, sizeof(zig_f##w)); \
5935 return res; \
5936 } \
5937 static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \
5938 zig_f##w res; \
5939 memcpy(&res, &arg, sizeof(zig_f##w)); \
5940 return res; \
5941 } \
5942 static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \
5943 UnsignedReprType res; \
5944 memcpy(&res, &arg, sizeof(zig_f##w)); \
5945 return zig_u##iw##_truncate_u##iw(res, w); \
5946 } \
5947 static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \
5948 SignedReprType res; \
5949 memcpy(&res, &arg, sizeof(zig_f##w)); \
5950 return zig_i##iw##_truncate_i##iw(res, w); \
39005951 }
3901zig_bitCast_float(f16, uint16_t)
3902zig_bitCast_float(f32, uint32_t)
3903zig_bitCast_float(f64, uint64_t)
3904zig_bitCast_float(f80, zig_u128)
3905zig_bitCast_float(f128, zig_u128)
5952zig_bitCast_float(16, 16, uint16_t, int16_t)
5953zig_bitCast_float(32, 32, uint32_t, int32_t)
5954zig_bitCast_float(64, 64, uint64_t, int64_t)
5955#if zig_has_f80
5956zig_bitCast_float(80, 128, zig_u128, zig_i128)
5957#else
5958static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) {
5959 return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg));
5960}
5961static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) {
5962 return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg));
5963}
5964static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) {
5965 return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5966}
5967static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) {
5968 return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg));
5969}
5970#endif
5971static inline zig_f80 zig_f80_bitCast_big(const void *arg) {
5972 return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80)));
5973}
5974static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) {
5975 if (res_is_signed) {
5976 zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits);
5977 } else {
5978 zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits);
5979 }
5980}
5981#if zig_has_f128
5982zig_bitCast_float(128, 128, zig_u128, zig_i128)
5983#else
5984static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) {
5985 return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg));
5986}
5987static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) {
5988 return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg));
5989}
5990static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) {
5991 return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5992}
5993static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) {
5994 return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg));
5995}
5996#endif
39065997
3907#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \
3908 zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3909 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \
5998#define zig_convert_float_00(ResType, operation, ArgType, version) \
5999 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6000 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \
6001 return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
6002 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg)
6003#define zig_convert_float_01(ResType, operation, ArgType, version) \
6004 zig_convert_float_00(ResType, operation, ArgType, version)
6005#define zig_convert_float_10(ResType, operation, ArgType, version) \
6006 zig_convert_float_00(ResType, operation, ArgType, version)
6007#define zig_convert_float_11(ResType, operation, ArgType, version) \
6008 return (ResType)arg
6009#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \
39106010 static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
39116011 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
3912 ResType res; \
3913 ExternResType extern_res; \
3914 ExternArgType extern_arg; \
3915 memcpy(&extern_arg, &arg, sizeof(extern_arg)); \
3916 extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
3917 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \
3918 memcpy(&res, &extern_res, sizeof(res)); \
3919 return extern_res; \
3920 }
3921zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)
3922zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)
3923zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
3924zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
3925zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)
3926zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
3927zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
3928zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)
3929zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
3930zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
3931zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)
3932zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)
3933zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)
3934zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2)
3935zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2)
3936zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2)
3937zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
3938zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)
3939
3940#ifdef __ARM_EABI__
3941
3942zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64);
3943static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); }
3944
3945zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32);
3946static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); }
3947
3948#else /* __ARM_EABI__ */
3949
3950zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
3951zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
3952
3953#endif /* __ARM_EABI__ */
3954
3955#define zig_float_negate_builtin_0(w, c, sb) \
3956 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
3957#define zig_float_negate_builtin_1(w, c, sb) -arg
3958#define zig_float_negate_builtin(w, c, sb) \
6012 zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \
6013 zig_has_##arg_when)(ResType, operation, ArgType, version); \
6014 }
6015
6016#define zig_convert_floats(SmallType, BigType) \
6017 zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \
6018 zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2)
6019zig_convert_floats(f16, f32)
6020zig_convert_floats(f16, f64)
6021zig_convert_floats(f16, f80)
6022zig_convert_floats(f16, f128)
6023zig_convert_floats(f32, f64)
6024zig_convert_floats(f32, f80)
6025zig_convert_floats(f32, f128)
6026zig_convert_floats(f64, f80)
6027zig_convert_floats(f64, f128)
6028zig_convert_floats(f80, f128)
6029
6030#define zig_float_negate_builtin_0(w, sb) \
6031 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb))
6032#define zig_float_negate_builtin_1(w, sb) -arg
6033#define zig_float_negate_builtin(w, sb) \
39596034 static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \
3960 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \
6035 return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \
39616036 }
3962zig_float_negate_builtin(16, , UINT16_C(1) << 15 )
3963zig_float_negate_builtin(32, , UINT32_C(1) << 31 )
3964zig_float_negate_builtin(64, , UINT64_C(1) << 63 )
3965zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))
3966zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
6037zig_float_negate_builtin(16, UINT16_C(1) << 15)
6038zig_float_negate_builtin(32, UINT32_C(1) << 31)
6039zig_float_negate_builtin(64, UINT64_C(1) << 63)
6040
6041#undef zig_float_negate_builtin_0
6042#define zig_float_negate_builtin_0(w, sb) \
6043 zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb))
6044zig_float_negate_builtin(80, UINT16_C(1) << 15)
6045
6046#undef zig_float_negate_builtin_0
6047#define zig_float_negate_builtin_0(w, sb) \
6048 zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg))
6049zig_float_negate_builtin(128, UINT64_C(1) << 63)
39676050
39686051#define zig_float_less_builtin_0(Type, operation) \
3969 zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
6052 zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \
39706053 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
39716054 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
3972 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
6055 return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
39736056 }
39746057#define zig_float_less_builtin_1(Type, operation) \
39756058 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
......@@ -3994,13 +6077,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
39946077 return lhs operator rhs; \
39956078 }
39966079
6080#define zig_float_builtins(w) \
6081 zig_common_float_builtins(w) \
6082 zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \
6083 zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, )
39976084#define zig_common_float_builtins(w) \
3998 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
3999 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
4000 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \
4001 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \
4002 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
4003 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
6085 zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \
6086 zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \
6087 zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \
6088 zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \
6089 zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \
6090 zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \
6091 zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \
6092 zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \
6093 zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \
6094 zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \
6095\
6096 static inline void zig_expand_concat(zig_expand_concat(zig_fix, \
6097 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6098 zig_extern void zig_expand_concat(zig_expand_concat(__fix, \
6099 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6100 zig_expand_concat(zig_expand_concat(__fix, \
6101 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6102 } \
6103\
6104 static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \
6105 zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \
6106 zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \
6107 zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \
6108 zig_expand_concat(zig_expand_concat(__fixuns, \
6109 zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \
6110 } \
6111\
6112 static inline zig_f##w zig_expand_concat(zig_floatei, \
6113 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6114 zig_extern zig_f##w zig_expand_concat(__floatei, \
6115 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6116 return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6117 } \
6118\
6119 static inline zig_f##w zig_expand_concat(zig_floatunei, \
6120 zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \
6121 zig_extern zig_f##w zig_expand_concat(__floatunei, \
6122 zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \
6123 return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \
6124 } \
6125\
40046126 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
40056127 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
40066128 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \
......@@ -4031,82 +6153,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
40316153 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \
40326154 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \
40336155\
4034 static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
6156 static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
40356157 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
40366158 } \
40376159\
4038 static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
6160 static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \
40396161 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
40406162 } \
40416163\
4042 static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \
6164 static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \
40436165 return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \
40446166 } \
40456167\
40466168 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
4047 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
6169 return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \
40486170 }
4049zig_common_float_builtins(16)
4050zig_common_float_builtins(32)
4051zig_common_float_builtins(64)
4052zig_common_float_builtins(80)
4053zig_common_float_builtins(128)
4054
4055#define zig_float_builtins(w) \
4056 zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
4057 zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
4058 zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
4059 zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
4060 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
4061 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, )
40626171zig_float_builtins(16)
4063zig_float_builtins(80)
4064zig_float_builtins(128)
4065
4066#ifdef __ARM_EABI__
4067
4068zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32);
4069static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); }
4070
4071zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32);
4072static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); }
4073
4074zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32);
4075static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); }
4076
4077zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t);
4078static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); }
4079
4080zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t);
4081static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); }
4082
4083zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t);
4084static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); }
4085
4086zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64);
4087static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); }
4088
4089zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64);
4090static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); }
4091
4092zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64);
4093static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); }
4094
4095zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t);
4096static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); }
4097
4098zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t);
4099static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); }
4100
4101zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t);
4102static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); }
4103
4104#else /* __ARM_EABI__ */
4105
41066172zig_float_builtins(32)
41076173zig_float_builtins(64)
4108
4109#endif /* __ARM_EABI__ */
6174zig_float_builtins(80)
6175#if defined(zig_x86_32)
6176zig_common_float_builtins(128)
6177static inline zig_f128 zig_floattitf(zig_i128 arg) {
6178 extern zig_f128 __floattitf(zig_f128 arg);
6179 return __floattitf(zig_f128_bitCast_i128(arg));
6180}
6181static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6182 extern zig_f128 __floatuntitf(zig_f128 arg);
6183 return __floatuntitf(zig_f128_bitCast_u128(arg));
6184}
6185#elif defined(zig_x86_64) && defined(zig_windows)
6186zig_common_float_builtins(128)
6187static inline zig_f128 zig_floattitf(zig_i128 arg) {
6188 extern zig_f128 __floattitf(zig_i128 arg);
6189 return __floattitf(arg);
6190}
6191static inline zig_f128 zig_floatuntitf(zig_u128 arg) {
6192 extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi);
6193 return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg));
6194}
6195#else
6196zig_float_builtins(128)
6197#endif
41106198
41116199/* ============================ Atomics Support ============================= */
41126200
......@@ -4410,19 +6498,19 @@ typedef int zig_memory_order;
44106498 } \
44116499 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
44126500 (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
4413 } \
6501 } \
44146502 static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
44156503 return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44166504 } \
44176505 static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \
4418 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6506 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44196507 _ReadWriteBarrier(); \
4420 return val; \
6508 return value; \
44216509 } \
44226510 static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \
4423 Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
6511 Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44246512 _ReadWriteBarrier(); \
4425 return val; \
6513 return value; \
44266514 }
44276515
44286516zig_msvc_atomics( u8, uint8_t, char, 8, 8)
......@@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
44656553 zig_##Type result; \
44666554 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44676555 _ReadWriteBarrier(); \
4468 memcpy(&result, &initial, sizeof(result)); \
6556 memcpy(&result, &initial, sizeof(result)); \
44696557 return result; \
44706558 } \
44716559 static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
44726560 zig_##Type result; \
44736561 SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
44746562 _ReadWriteBarrier(); \
4475 memcpy(&result, &initial, sizeof(result)); \
6563 memcpy(&result, &initial, sizeof(result)); \
44766564 return result; \
44776565 }
44786566
......@@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat
45026590}
45036591
45046592static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {
4505 void* val = (void*)__iso_volatile_load32(obj);
6593 void* value = (void*)__iso_volatile_load32(obj);
45066594 _ReadWriteBarrier();
4507 return val;
6595 return value;
45086596}
45096597
45106598static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) {
......@@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat
45326620}
45336621
45346622static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {
4535 void* val = (void*)__iso_volatile_load64(obj);
6623 void* value = (void*)__iso_volatile_load64(obj);
45366624 _ReadWriteBarrier();
4537 return val;
6625 return value;
45386626}
45396627
45406628static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/behavior/abs.zig-2
......@@ -144,7 +144,6 @@ test "@abs big int <= 128 bits" {
144144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
148147
149148 try comptime testAbsSignedBigInt();
150149 try testAbsSignedBigInt();
......@@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void {
256255
257256test "@abs int vectors" {
258257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
260258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
261259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
262260 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/align.zig+32-13
......@@ -129,8 +129,7 @@ test "alignment and size of structs with 128-bit fields" {
129129 y: u8,
130130 };
131131 const expected = switch (builtin.cpu.arch) {
132 .s390x,
133 => .{
132 .s390x => .{
134133 .a_align = 8,
135134 .a_size = 16,
136135
......@@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" {
142141 .u129_align = 8,
143142 .u129_size = 24,
144143 },
145
144 .x86 => switch (builtin.os.tag) {
145 else => .{
146 .a_align = 4,
147 .a_size = 16,
148
149 .b_align = 4,
150 .b_size = 20,
151
152 .u128_align = 4,
153 .u128_size = 16,
154 .u129_align = 4,
155 .u129_size = 20,
156 },
157 .uefi, .windows => .{
158 .a_align = 8,
159 .a_size = 16,
160
161 .b_align = 8,
162 .b_size = 24,
163
164 .u128_align = 8,
165 .u128_size = 16,
166 .u129_align = 8,
167 .u129_size = 24,
168 },
169 },
146170 .amdgcn,
147171 .arm,
148172 .armeb,
......@@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" {
155179 .powerpc,
156180 .powerpcle,
157181 .riscv32,
182 .sparc,
158183 => .{
159184 .a_align = 8,
160185 .a_size = 16,
161186
162 .b_align = 16,
163 .b_size = 32,
187 .b_align = 8,
188 .b_size = 24,
164189
165190 .u128_align = 8,
166191 .u128_size = 16,
......@@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" {
178203 .nvptx64,
179204 .powerpc64,
180205 .powerpc64le,
181 .sparc,
182206 .sparc64,
183207 .riscv64,
184208 .wasm32,
185209 .wasm64,
186 .x86,
187210 .x86_64,
188211 => .{
189212 .a_align = 16,
......@@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" {
200223
201224 else => return error.SkipZigTest,
202225 };
203 const min_struct_align = if (builtin.zig_backend == .stage2_c) if (builtin.cpu.arch == .s390x) 8 else 16 else 0;
204226 comptime {
205 assert(@alignOf(A) == @max(expected.a_align, min_struct_align));
227 assert(@alignOf(A) == expected.a_align);
206228 assert(@sizeOf(A) == expected.a_size);
207229
208 assert(@alignOf(B) == @max(expected.b_align, min_struct_align));
230 assert(@alignOf(B) == expected.b_align);
209231 assert(@sizeOf(B) == expected.b_size);
210232
211233 assert(@alignOf(u128) == expected.u128_align);
......@@ -547,8 +569,6 @@ test "sub-aligned pointer field access" {
547569}
548570
549571test "alignment of zero-bit types is respected" {
550 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
551 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
552572 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
553573 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
554574
......@@ -582,7 +602,6 @@ test "zero-bit fields in extern struct pad fields appropriately" {
582602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
583603 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
584604 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
586605
587606 const S = extern struct {
588607 x: u8,
test/behavior/basic.zig-2
......@@ -800,7 +800,6 @@ test "extern variable with non-pointer opaque type" {
800800 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
801801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
804803 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
805804
806805 @export(&var_to_export, .{ .name = "opaque_extern_var" });
......@@ -1398,7 +1397,6 @@ test "allocation and looping over 3-byte integer" {
13981397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13991398 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14001399 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1401 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag.isDarwin()) return error.SkipZigTest; // TODO
14021400
14031401 try expect(@sizeOf(u24) == 4);
14041402 try expect(@sizeOf([1]u24) == 4);
test/behavior/bit_shifting.zig-1
......@@ -147,7 +147,6 @@ test "Saturating Shift Left where lhs is of a computed type" {
147147
148148test "Saturating Shift Left" {
149149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
151150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
152151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
153152 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/bitcast.zig+1-6
......@@ -210,7 +210,6 @@ test "triple level result location with bitcast sandwich passed as tuple element
210210
211211test "@bitCast packed struct of floats" {
212212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
214213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
215214 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216215 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" {
247246
248247test "comptime @bitCast packed struct to int and back" {
249248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
251249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
252250 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
253251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" {
283281test "bitcast vector to integer and back" {
284282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
285283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
286 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
287284 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
288285 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
289286
......@@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 {
329326}
330327test "bitcast nan float does not modify signaling bit" {
331328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
333329 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
334330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
335331 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
332 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
336333
337334 const snan_u16: u16 = 0x7D00;
338335 const snan_u32: u32 = 0x7FA00000;
......@@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" {
383380test "@bitCast of packed struct of bools all true" {
384381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
385382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
387383 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
388384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
389385
......@@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" {
404400test "@bitCast of packed struct of bools all false" {
405401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
406402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
408403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
409404
410405 const P = packed struct {
test/behavior/cast.zig+4-18
......@@ -134,7 +134,6 @@ test "@intFromFloat > 128 bits" {
134134 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
135135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136136 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
138137
139138 try testIntFromFloat(f16, 1024, u140, 1024);
140139 try testIntFromFloat(f16, -1024, i140, -1024);
......@@ -160,7 +159,6 @@ test "@floatFromInt > 128 bits" {
160159 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
161160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162161 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
163 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
164162
165163 try testFloatFromInt(u140, 1024, f16, 1024);
166164 try testFloatFromInt(i140, -1024, f16, -1024);
......@@ -182,8 +180,8 @@ test "@floatFromInt(f80)" {
182180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
183181 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184182 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
186183 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
184 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
187185
188186 const S = struct {
189187 fn doTheTest(comptime Int: type) !void {
......@@ -207,7 +205,7 @@ test "@floatFromInt(f80)" {
207205 try S.doTheTest(i64);
208206 try S.doTheTest(i80);
209207 try S.doTheTest(i128);
210 // try S.doTheTest(i256); // TODO missing compiler_rt symbols
208 try S.doTheTest(i256);
211209 try comptime S.doTheTest(i31);
212210 try comptime S.doTheTest(i32);
213211 try comptime S.doTheTest(i45);
......@@ -281,6 +279,7 @@ test "type coercion from int to float" {
281279test "@intFromFloat" {
282280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
283281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
282
284283 try testIntFromFloats();
285284 try comptime testIntFromFloats();
286285}
......@@ -1473,11 +1472,6 @@ fn foobar(func: PFN_void) !void {
14731472test "cast function with an opaque parameter" {
14741473 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14751474
1476 if (builtin.zig_backend == .stage2_c) {
1477 // https://github.com/ziglang/zig/issues/16845
1478 return error.SkipZigTest;
1479 }
1480
14811475 const Container = struct {
14821476 const Ctx = opaque {};
14831477 ctx: *Ctx,
......@@ -1724,9 +1718,7 @@ test "cast f16 to wider types" {
17241718 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17251719 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17261720 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1727 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
17281721 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1729 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
17301722
17311723 const S = struct {
17321724 fn doTheTest() !void {
......@@ -1831,21 +1823,15 @@ test "pointer to empty struct literal to mutable slice" {
18311823
18321824test "coerce between pointers of compatible differently-named floats" {
18331825 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1834 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;
18351826 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18361827 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18371828 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18381829
1839 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1840 // https://github.com/ziglang/zig/issues/12396
1841 return error.SkipZigTest;
1842 }
1843
18441830 const F = switch (@typeInfo(c_longdouble).float.bits) {
18451831 64 => f64,
18461832 80 => f80,
18471833 128 => f128,
1848 else => @compileError("unreachable"),
1834 else => comptime unreachable,
18491835 };
18501836 var f1: F = 12.34;
18511837 const f2: *c_longdouble = &f1;
test/behavior/cast_int.zig-1
......@@ -168,7 +168,6 @@ test "@intCast <= 64 bits" {
168168
169169test "@intCast > 128 bits" {
170170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
171 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
172171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
173172
174173 try testIntCast(u8, 123, u140, 123);
test/behavior/eval.zig-1
......@@ -513,7 +513,6 @@ test "runtime 128 bit integer division" {
513513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
514514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
515515 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
516 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
517516 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
518517
519518 var a: u128 = 152313999999999991610955792383;
test/behavior/extern.zig-1
......@@ -3,7 +3,6 @@ const std = @import("std");
33const expect = std.testing.expect;
44
55test "anyopaque extern symbol" {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
98
test/behavior/field_parent_ptr.zig-3
......@@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
586586}
587587
588588test "@fieldParentPtr unaligned packed struct" {
589 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
590589 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
591590 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
592591 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" {
725724}
726725
727726test "@fieldParentPtr aligned packed struct" {
728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
729727 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
730728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
731729 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -1897,7 +1895,6 @@ test "@fieldParentPtr packed union" {
18971895}
18981896
18991897test "@fieldParentPtr tagged union all zero-bit fields" {
1900 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
19011898 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19021899 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19031900
test/behavior/floatop.zig+6-46
......@@ -118,7 +118,6 @@ fn testMul(comptime T: type) !void {
118118test "cmp f16" {
119119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120120 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
121 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
122121
123122 try testCmp(f16);
124123 try comptime testCmp(f16);
......@@ -127,7 +126,6 @@ test "cmp f16" {
127126test "cmp f32" {
128127 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
129128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
130 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
131129
132130 try testCmp(f32);
133131 try comptime testCmp(f32);
......@@ -142,7 +140,6 @@ test "cmp f64" {
142140
143141test "cmp f128" {
144142 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
146143 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
147144 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
148145
......@@ -152,7 +149,6 @@ test "cmp f128" {
152149
153150test "cmp f80/c_longdouble" {
154151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
156152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157153 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
158154
......@@ -220,7 +216,6 @@ test "vector cmp f16" {
220216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
221217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222218 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
224219 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
225220
226221 try testCmpVector(f16);
......@@ -253,7 +248,6 @@ test "vector cmp f64" {
253248test "vector cmp f128" {
254249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
255250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
257251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
258252 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
259253 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;
......@@ -381,11 +375,7 @@ test "@sqrt f80/f128/c_longdouble" {
381375 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
382376 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
383377 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
384
385 if (builtin.os.tag == .freebsd) {
386 // TODO https://github.com/ziglang/zig/issues/10875
387 return error.SkipZigTest;
388 }
378 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
389379
390380 try testSqrt(f80);
391381 try comptime testSqrt(f80);
......@@ -431,9 +421,9 @@ fn testSqrt(comptime T: type) !void {
431421 var inf: T = math.inf(T);
432422 try expect(math.isPositiveInf(@sqrt(inf)));
433423 var zero: T = 0.0;
434 try expect(@sqrt(zero) == 0.0);
424 try expect(math.isPositiveZero(@sqrt(zero)));
435425 var neg_zero: T = -0.0;
436 try expect(@sqrt(neg_zero) == 0.0);
426 try expect(math.isNegativeZero(@sqrt(neg_zero)));
437427 var neg_one: T = -1.0;
438428 try expect(math.isNan(@sqrt(neg_one)));
439429 var nan: T = math.nan(T);
......@@ -947,7 +937,7 @@ test "@log2 with vectors" {
947937 builtin.cpu.arch == .aarch64 and
948938 builtin.os.tag == .windows) return error.SkipZigTest;
949939
950 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) {
940 if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) {
951941 // https://codeberg.org/ziglang/zig/issues/35518
952942 return error.SkipZigTest;
953943 }
......@@ -1054,7 +1044,6 @@ test "@abs f32/f64" {
10541044
10551045test "@abs f80/f128/c_longdouble" {
10561046 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1057 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
10581047 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10591048 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10601049 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -1172,16 +1161,10 @@ test "@floor f32/f64" {
11721161
11731162test "@floor f80/f128/c_longdouble" {
11741163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1175 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
11761164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11771165 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11781166 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11791167
1180 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1181 // https://github.com/ziglang/zig/issues/12602
1182 return error.SkipZigTest;
1183 }
1184
11851168 try testFloor(f80);
11861169 try comptime testFloor(f80);
11871170 try testFloor(f128);
......@@ -1261,16 +1244,10 @@ test "@ceil f32/f64" {
12611244
12621245test "@ceil f80/f128/c_longdouble" {
12631246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1264 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
12651247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12661248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12671249 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12681250
1269 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1270 // https://github.com/ziglang/zig/issues/12602
1271 return error.SkipZigTest;
1272 }
1273
12741251 try testCeil(f80);
12751252 try comptime testCeil(f80);
12761253 try testCeil(f128);
......@@ -1281,16 +1258,10 @@ test "@ceil f80/f128/c_longdouble" {
12811258
12821259test "@ceil f80 maxInt(u64)" {
12831260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1284 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
12851261 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12861262 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12871263 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12881264
1289 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1290 // https://github.com/ziglang/zig/issues/12602
1291 return error.SkipZigTest;
1292 }
1293
12941265 var x: u64 = std.math.maxInt(u64);
12951266 x = x;
12961267 const float: f80 = @floatFromInt(x);
......@@ -1368,16 +1339,10 @@ test "@trunc f32/f64" {
13681339
13691340test "@trunc f80/f128/c_longdouble" {
13701341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
13721342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13731343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13741344 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13751345
1376 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1377 // https://github.com/ziglang/zig/issues/12602
1378 return error.SkipZigTest;
1379 }
1380
13811346 try testTrunc(f80);
13821347 try comptime testTrunc(f80);
13831348 try testTrunc(f128);
......@@ -1440,11 +1405,6 @@ test "neg f16" {
14401405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14411406 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14421407
1443 if (builtin.os.tag == .freebsd) {
1444 // TODO file issue to track this failure
1445 return error.SkipZigTest;
1446 }
1447
14481408 try testNeg(f16);
14491409 try comptime testNeg(f16);
14501410}
......@@ -1501,9 +1461,9 @@ fn testNeg(comptime T: type) !void {
15011461
15021462 // subnormals
15031463 var zero: T = 0.0;
1504 try expect(-zero == -0.0);
1464 try expect(math.isNegativeZero(-zero));
15051465 var neg_zero: T = -0.0;
1506 try expect(-neg_zero == 0.0);
1466 try expect(math.isPositiveZero(-neg_zero));
15071467 var true_min: T = math.floatTrueMin(T);
15081468 try expect(-true_min == -math.floatTrueMin(T));
15091469 var neg_true_min: T = -math.floatTrueMin(T);
test/behavior/fn.zig-1
......@@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn {
147147
148148test "extern struct with stdcallcc fn pointer" {
149149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest;
151150 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
152151
153152 const S = extern struct {
test/behavior/math.zig-35
......@@ -873,7 +873,6 @@ test "umax wrapped squaring" {
873873test "128-bit multiplication" {
874874 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
875875 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
877876 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
878877
879878 {
......@@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" {
968967 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
969968 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
970969 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
971 if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest;
972970
973971 try testAddWithOverflow(u129, 4, 105, 109, 0);
974972 try testAddWithOverflow(u129, 1000, 100, 1100, 0);
......@@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" {
11361134
11371135test "@mulWithOverflow bitsize 128 bits" {
11381136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1139 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11401137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11411138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11421139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" {
11631160
11641161test "@mulWithOverflow > 128 bits" {
11651162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11671163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11681164
11691165 try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0);
......@@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" {
11931189
11941190test "@mulWithOverflow bitsize 256 bits" {
11951191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1196 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11971192 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11981193 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11991194
......@@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" {
12981293 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12991294 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13001295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1301 if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest;
13021296
13031297 try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1);
13041298 try testSubWithOverflow(u129, 1000, 100, 900, 0);
......@@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" {
13891383
13901384test "@shlWithOverflow > 128 bits" {
13911385 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1392 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
13931386 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13941387
13951388 try testShlWithOverflow(u140, 1 << 100, 20, 1 << 120, 0);
......@@ -1419,7 +1412,6 @@ fn testAnd(comptime T: type, a: T, b: T, expected: T) !void {
14191412
14201413test "and > 128 bits" {
14211414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1422 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14231415
14241416 try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88);
14251417 try testAnd(u140, maxInt(u140), 1 << 100, 1 << 100);
......@@ -1448,7 +1440,6 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void {
14481440
14491441test "or > 128 bits" {
14501442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1451 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14521443
14531444 try testOr(u140, 0, 1 << 139, 1 << 139);
14541445 try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf);
......@@ -1477,7 +1468,6 @@ fn testXor(comptime T: type, a: T, b: T, expected: T) !void {
14771468
14781469test "xor > 128 bits" {
14791470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1480 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
14811471
14821472 try testXor(u140, 0, maxInt(u140), maxInt(u140));
14831473 try testXor(u140, 1 << 139, 1 << 139, 0);
......@@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void {
15061496
15071497test "not > 128 bits" {
15081498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1509 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15101499
15111500 try testNot(u140, 0, maxInt(u140));
15121501 try testNot(u140, maxInt(u140), 0);
......@@ -1535,7 +1524,6 @@ fn testShl(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void {
15351524
15361525test "shl > 128 bits" {
15371526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1538 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15391527
15401528 try testShl(u140, 1 << 5, 10, 1 << 15);
15411529 try testShl(u140, 3, 138, (1 << 139) | (1 << 138));
......@@ -1564,7 +1552,6 @@ fn testShr(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void {
15641552
15651553test "shr > 128 bits" {
15661554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1567 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15681555
15691556 try testShr(u140, 1 << 139, 39, 1 << 100);
15701557 try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1);
......@@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void {
15931580
15941581test "@clz > 128 bits" {
15951582 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1596 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
15971583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15981584
15991585 try testClz(u140, 0, 140);
......@@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void {
16231609
16241610test "@ctz > 128 bits" {
16251611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1626 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16271612 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16281613
16291614 try testCtz(u140, 0, 140);
......@@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void {
16531638
16541639test "@popCount > 128 bits" {
16551640 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1656 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16571641 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16581642
16591643 try testPopCount(u140, 0, 0);
......@@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void {
16831667
16841668test "@bitReverse > 128 bits" {
16851669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1686 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16871670 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16881671
16891672 try testBitReverse(u140, 1 << 139, 1);
......@@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void {
17131696
17141697test "@byteSwap > 128 bits" {
17151698 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1716 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17171699 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17181700
17191701 try testByteSwap(u144, 1 << 136, 1);
......@@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void {
17431725
17441726test "@max > 128 bits" {
17451727 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1746 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17471728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17481729
17491730 try testMax(u140, 0, maxInt(u140), maxInt(u140));
......@@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void {
17731754
17741755test "@min > 128 bits" {
17751756 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1776 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
17771757 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17781758
17791759 try testMin(u140, 0, maxInt(u140), 0);
......@@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void {
18031783
18041784test "@abs > 128 bits" {
18051785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1806 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18071786
18081787 try testAbs(u140, 0, 0);
18091788 try testAbs(u140, 1 << 139, 1 << 139);
......@@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void {
18271806
18281807test "@rem > 128 bits" {
18291808 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1830 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18311809 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18321810
18331811 try testRem(u140, 0, maxInt(u140), 0);
......@@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void {
18551833
18561834test "@mod > 128 bits" {
18571835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1858 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18591836 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18601837
18611838 try testMod(u140, 0, maxInt(u140), 0);
......@@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo
18831860
18841861test "@divFloor > 128 bits" {
18851862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1886 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18871863 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18881864
18891865 try testDivFloor(u140, 0, maxInt(u140), 0);
......@@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi
19121888
19131889test "@divCeil > 128 bits" {
19141890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1915 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
19161891 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19171892
19181893 try testDivCeil(u140, 0, maxInt(u140), 0);
......@@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo
19411916
19421917test "@divTrunc > 128 bits" {
19431918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1944 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
19451919 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19461920
19471921 try testDivTrunc(u140, 0, maxInt(u140), 0);
......@@ -2166,14 +2140,8 @@ test "remainder division" {
21662140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
21672141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21682142 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2169 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
21702143 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21712144
2172 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
2173 // https://github.com/ziglang/zig/issues/12602
2174 return error.SkipZigTest;
2175 }
2176
21772145 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
21782146
21792147 try comptime remdiv(f16);
......@@ -2315,7 +2283,6 @@ test "@round f80" {
23152283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23162284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23172285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2318 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
23192286 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23202287
23212288 try testRound(f80, 12.0);
......@@ -2326,7 +2293,6 @@ test "@round f128" {
23262293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23272294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23282295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2329 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
23302296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23312297
23322298 try testRound(f128, 12.0);
......@@ -2366,7 +2332,6 @@ test "NaN comparison" {
23662332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23672333 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
23682334 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2369 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
23702335
23712336 try testNanEqNan(f16);
23722337 try testNanEqNan(f32);
test/behavior/maximum_minimum.zig-1
......@@ -115,7 +115,6 @@ test "@min/max for floats" {
115115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
116116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
117117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
119118 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
120119
121120 const S = struct {
test/behavior/muladd.zig-4
......@@ -49,7 +49,6 @@ test "@mulAdd f80" {
4949 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5050 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
5352 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5453
5554 try comptime testMulAdd80();
......@@ -68,7 +67,6 @@ test "@mulAdd f128" {
6867 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6968 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7069 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
7270 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7371
7472 try comptime testMulAdd128();
......@@ -169,7 +167,6 @@ test "vector f80" {
169167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
170168 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
171169 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
173170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
174171
175172 try comptime vector80();
......@@ -194,7 +191,6 @@ test "vector f128" {
194191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
195192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
196193 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
197 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
198194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
199195
200196 try comptime vector128();
test/behavior/packed-struct.zig-4
......@@ -404,7 +404,6 @@ test "nested packed struct field pointers" {
404404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
405405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
408407 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
409408 const S2 = packed struct {
410409 base: u8,
......@@ -579,7 +578,6 @@ test "packed struct fields modification" {
579578}
580579
581580test "nested packed struct field access test" {
582 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
583581 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
584582 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
585583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" {
733731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
734732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
735733 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
736 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
737734 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
738735
739736 const S = struct {
......@@ -1171,7 +1168,6 @@ test "packed struct equality" {
11711168
11721169test "packed struct equality ignores padding bits" {
11731170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11751171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11761172
11771173 const S = packed struct { b: bool };
test/behavior/pointers.zig+1-1
......@@ -275,7 +275,7 @@ test "compare equality of optional and non-optional pointer" {
275275}
276276
277277test "allowzero pointer and slice" {
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
279279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
280280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281281 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/saturating_arithmetic.zig-7
......@@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" {
144144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
148147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
149148
150149 try testSatMul(u8, 0, maxInt(u8), 0);
......@@ -238,7 +237,6 @@ test "saturating multiplication" {
238237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
239238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
240239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
242240 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
243241
244242 const S = struct {
......@@ -313,7 +311,6 @@ test "saturating shift-left" {
313311
314312test "saturating shift-left large rhs" {
315313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
316 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
317314 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
318315 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
319316 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
......@@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" {
361358
362359test "sat add > 128 bits" {
363360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
364 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
365361 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
366362
367363 try testSatAdd(u140, 0, 0, 0);
......@@ -377,7 +373,6 @@ test "sat add > 128 bits" {
377373
378374test "sat sub > 128 bits" {
379375 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
381376 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
382377
383378 try testSatSub(u140, 0, 1, 0);
......@@ -393,7 +388,6 @@ test "sat sub > 128 bits" {
393388
394389test "sat mul > 128 bits" {
395390 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
397391 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
398392
399393 try testSatMul(u140, 0, maxInt(u140), 0);
......@@ -409,7 +403,6 @@ test "sat mul > 128 bits" {
409403
410404test "sat shl > 128 bits" {
411405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
412 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
413406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
414407
415408 try testSatShl(u140, 0, u8, 17, 0);
test/behavior/struct.zig+2-6
......@@ -535,7 +535,6 @@ test "zero-bit field in packed struct" {
535535test "packed struct with non-ABI-aligned field" {
536536 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
537537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
539538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
540539 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
541540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" {
792791 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
793792 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
794793 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
795 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
796794 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
797795
798796 const U = union(enum) {
......@@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" {
15391537}
15401538
15411539test "struct field pointer has correct alignment" {
1542 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15431540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15441541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15451542 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" {
15691566}
15701567
15711568test "extern struct field pointer has correct alignment" {
1572 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15731569 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15741570 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15751571 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" {
20072003}
20082004
20092005test "struct containing optional pointer to array of @This()" {
2010 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
20112006 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
20122007
20132008 const S = struct {
......@@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" {
22662261
22672262test "struct contains underaligned field with overaligned pointer to itself" {
22682263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2269 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2265
22702266 const S = struct {
22712267 ptr: *align(8) @This() align(1),
22722268 };
test/behavior/switch.zig+1-1
......@@ -1267,7 +1267,7 @@ test "switch with complex item expressions" {
12671267test "switch evaluation order" {
12681268 const eu: anyerror!u32 = 0;
12691269 _ = eu catch |err| switch (err) {
1270 if (true) @compileError("unreachable") => unreachable,
1270 if (true) comptime unreachable => unreachable,
12711271 else => unreachable,
12721272 };
12731273}
test/behavior/switch_loop.zig+1-2
......@@ -223,7 +223,6 @@ test "unanalyzed continue with operand" {
223223
224224test "switch loop on larger than pointer integer" {
225225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
226 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
227226 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
228227
229228 var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;
......@@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" {
268267
269268test "switch loop with discarded tag capture" {
270269 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
271 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
270
272271 const S = struct {
273272 const U = union(enum) {
274273 a: u32,
test/behavior/switch_on_captured_error.zig+3-3
......@@ -243,7 +243,7 @@ test "switch on error union catch capture" {
243243 var a: error{}!u64 = 0;
244244 _ = &a;
245245 const b = a catch |err| switch (err) {
246 undefined => @compileError("unreachable"),
246 undefined => comptime unreachable,
247247 };
248248 try expectEqual(@as(u64, 0), b);
249249 }
......@@ -829,7 +829,7 @@ test "switch on error union if else capture" {
829829 var a: error{}!u64 = 0;
830830 _ = &a;
831831 const b = if (a) |x| x else |err| switch (err) {
832 undefined => @compileError("unreachable"),
832 undefined => comptime unreachable,
833833 };
834834 try expectEqual(@as(u64, 0), b);
835835 }
......@@ -840,7 +840,7 @@ test "switch on error union if else capture" {
840840 var a: error{}!u64 = 0;
841841 _ = &a;
842842 const b = if (a) |*x| x.* else |err| switch (err) {
843 undefined => @compileError("unreachable"),
843 undefined => comptime unreachable,
844844 };
845845 try expectEqual(@as(u64, 0), b);
846846 }
test/behavior/threadlocal.zig-5
......@@ -9,11 +9,6 @@ test "thread local variable" {
99 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1111
12 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag.isDarwin()) {
13 // Fails due to register hazards.
14 return error.SkipZigTest;
15 }
16
1712 const S = struct {
1813 threadlocal var t: i32 = 1234;
1914 };
test/behavior/truncate.zig-1
......@@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void {
4949
5050test "@truncate > 128 bits" {
5151 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
5352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
5453
5554 try testTruncate(u140, 0, u128, 0);
test/behavior/union.zig+4-8
......@@ -1437,7 +1437,6 @@ test "coerce enum literal to union in result loc" {
14371437}
14381438
14391439test "defined-layout union field pointer has correct alignment" {
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14411440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14421441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14431442 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" {
14721471}
14731472
14741473test "undefined-layout union field pointer has correct alignment" {
1475 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14761474 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14771475 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14781476 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1611,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T {
16111609}
16121610
16131611test "reinterpret extern union" {
1612 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1613 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isRiscv32() and builtin.link_libc) return error.SkipZigTest;
1614 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest;
1615
16141616 if (true) {
16151617 // https://github.com/ziglang/zig/issues/19389
16161618 return error.SkipZigTest;
......@@ -1678,8 +1680,6 @@ test "reinterpret extern union" {
16781680 };
16791681
16801682 try comptime S.doTheTest();
1681
1682 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
16831683 try S.doTheTest();
16841684}
16851685
......@@ -1758,8 +1758,6 @@ test "reinterpret packed union" {
17581758 };
17591759
17601760 try comptime S.doTheTest();
1761
1762 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
17631761 try S.doTheTest();
17641762}
17651763
......@@ -1800,8 +1798,6 @@ test "reinterpret packed union inside packed struct" {
18001798 };
18011799
18021800 try comptime S.doTheTest();
1803
1804 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
18051801 try S.doTheTest();
18061802}
18071803
test/behavior/vector.zig+19-18
......@@ -128,13 +128,6 @@ test "vector float operators" {
128128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
129129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
130130 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
131 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
132
133 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
134 // Triggers an assertion with LLVM 18:
135 // https://github.com/ziglang/zig/issues/20680
136 return error.SkipZigTest;
137 }
138131
139132 const S = struct {
140133 fn doTheTest(T: type) !void {
......@@ -280,7 +273,6 @@ test "array to vector with element type coercion" {
280273 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281274 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
282275 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
283 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
284276
285277 const S = struct {
286278 fn doTheTest() !void {
......@@ -736,9 +728,7 @@ test "vector reduce operation" {
736728 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
737729 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
739 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
740731 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
741 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562
742732
743733 const S = struct {
744734 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
......@@ -776,6 +766,8 @@ test "vector reduce operation" {
776766 try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
777767 try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
778768 try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));
769 try testReduce(.Add, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 42.9));
770 try testReduce(.Add, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 42.9));
779771
780772 try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));
781773 try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));
......@@ -794,6 +786,8 @@ test "vector reduce operation" {
794786 try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));
795787 try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));
796788 try testReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0));
789 try testReduce(.Min, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, -100.0));
790 try testReduce(.Min, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, -100.0));
797791
798792 try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));
799793 try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));
......@@ -806,6 +800,8 @@ test "vector reduce operation" {
806800 try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));
807801 try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));
808802 try testReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9));
803 try testReduce(.Max, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, 10.0e9));
804 try testReduce(.Max, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, 10.0e9));
809805
810806 try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));
811807 try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));
......@@ -818,6 +814,8 @@ test "vector reduce operation" {
818814 try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
819815 try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
820816 try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));
817 try testReduce(.Mul, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 58430.7));
818 try testReduce(.Mul, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 58430.7));
821819
822820 try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));
823821 try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));
......@@ -825,6 +823,7 @@ test "vector reduce operation" {
825823 try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));
826824 try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));
827825 try testReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff));
826 try testReduce(.Or, [4]u80{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u80, 0xffffffff));
828827
829828 try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));
830829 try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));
......@@ -837,22 +836,32 @@ test "vector reduce operation" {
837836 const f16_nan = math.nan(f16);
838837 const f32_nan = math.nan(f32);
839838 const f64_nan = math.nan(f64);
839 const f80_nan = math.nan(f80);
840 const f128_nan = math.nan(f128);
840841
841842 try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
842843 try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
843844 try testReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
845 try testReduce(.Add, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan);
846 try testReduce(.Add, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan);
844847
845848 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));
846849 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));
847850 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9));
851 try testReduce(.Min, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, -1.9));
852 try testReduce(.Min, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, -1.9));
848853
849854 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));
850855 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));
851856 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0));
857 try testReduce(.Max, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, 100.0));
858 try testReduce(.Max, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, 100.0));
852859
853860 try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
854861 try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
855862 try testReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
863 try testReduce(.Mul, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan);
864 try testReduce(.Mul, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan);
856865 }
857866 };
858867
......@@ -1321,11 +1330,6 @@ test "byte vector initialized in inline function" {
13211330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13221331 if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
13231332
1324 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and comptime builtin.cpu.has(.x86, .avx512f)) {
1325 // TODO https://github.com/ziglang/zig/issues/13279
1326 return error.SkipZigTest;
1327 }
1328
13291333 const S = struct {
13301334 fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
13311335 return .{ e0, e1, e2, e3 };
......@@ -1437,7 +1441,6 @@ test "store packed vector element" {
14371441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14381442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14391443 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14411444 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14421445
14431446 var v = @Vector(4, u1){ 1, 1, 1, 1 };
......@@ -1469,7 +1472,6 @@ test "store vector with memset" {
14691472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14701473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14711474 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14731475 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14741476
14751477 var a: [5]@Vector(2, i1) = undefined;
......@@ -1610,7 +1612,6 @@ test "bitcast vector to array of smaller vectors" {
16101612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16111613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16121614 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1613 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
16141615
16151616 const u8x32 = @Vector(32, u8);
16161617 const u8x64 = @Vector(64, u8);
test/behavior/widening.zig-1
......@@ -41,7 +41,6 @@ test "float widening" {
4141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4242 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4343 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
44 if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest;
4544
4645 var a: f16 = 12.34;
4746 var b: f32 = a;
test/behavior/x86_64/unary.zig+1-1
......@@ -56,7 +56,7 @@ fn unary(comptime op: anytype, comptime opts: struct {
5656 f32 => libc_name ++ "f",
5757 f64 => libc_name,
5858 f80 => "__" ++ libc_name ++ "x",
59 f128 => libc_name ++ "q",
59 f128 => libc_name ++ "f128",
6060 else => break :libc,
6161 },
6262 .library_name = switch (@import("builtin").object_format) {
test/c_abi/cfuncs.c+256-20
......@@ -77,7 +77,7 @@ static void assert_or_panic(bool ok) {
7777# define ZIG_NO_COMPLEX
7878#endif
7979
80#ifdef ZIG_PPC32
80#ifdef __powerpc__
8181# define ZIG_NO_COMPLEX
8282#endif
8383
......@@ -408,7 +408,11 @@ void c_test_longdouble(void) {
408408 zig_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 10, 9);
409409}
410410
411#if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__)
411#ifndef __hexagon__
412#ifndef __loongarch__
413#ifndef __mips__
414#ifndef ZIG_PPC64
415#if !(defined(__i386__) && defined(_WIN32))
412416
413417typedef bool Vector_2_bool __attribute__((ext_vector_type(2)));
414418
......@@ -4657,6 +4661,10 @@ void c_test_vector_512_bool(void) {
46574661 });
46584662}
46594663
4664#endif
4665#endif
4666#endif
4667#endif
46604668#endif
46614669
46624670typedef uint8_t Vector_1_u8 __attribute__((vector_size(1 * sizeof(uint8_t))));
......@@ -15186,6 +15194,126 @@ void c_test_struct_f32_f32_f32_f32_f32(void) {
1518615194 zig_struct_f32_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32_f32){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11);
1518715195}
1518815196
15197struct Struct_array_1_f32 {
15198 float a[1];
15199};
15200
15201struct Struct_array_1_f32 zig_ret_struct_array_1_f32(void);
15202void zig_struct_array_1_f32(struct Struct_array_1_f32, size_t);
15203
15204struct Struct_array_1_f32 c_ret_struct_array_1_f32(void) {
15205 return (struct Struct_array_1_f32){ .a = { 4 } };
15206}
15207void c_struct_array_1_f32(struct Struct_array_1_f32 s, size_t i) {
15208 assert_or_panic(s.a[0] == 5);
15209 assert_or_panic(i == 6);
15210}
15211void c_test_struct_array_1_f32(void) {
15212 struct Struct_array_1_f32 s = zig_ret_struct_array_1_f32();
15213 assert_or_panic(s.a[0] == 1);
15214 zig_struct_array_1_f32((struct Struct_array_1_f32){ .a = { 2 } }, 3);
15215}
15216
15217struct Struct_array_2_f32 {
15218 float a[2];
15219};
15220
15221struct Struct_array_2_f32 zig_ret_struct_array_2_f32(void);
15222void zig_struct_array_2_f32(struct Struct_array_2_f32, size_t);
15223
15224struct Struct_array_2_f32 c_ret_struct_array_2_f32(void) {
15225 return (struct Struct_array_2_f32){ .a = { 6, 7 } };
15226}
15227void c_struct_array_2_f32(struct Struct_array_2_f32 s, size_t i) {
15228 assert_or_panic(s.a[0] == 8);
15229 assert_or_panic(s.a[1] == 9);
15230 assert_or_panic(i == 10);
15231}
15232void c_test_struct_array_2_f32(void) {
15233 struct Struct_array_2_f32 s = zig_ret_struct_array_2_f32();
15234 assert_or_panic(s.a[0] == 1);
15235 assert_or_panic(s.a[1] == 2);
15236 zig_struct_array_2_f32((struct Struct_array_2_f32){ .a = { 3, 4 } }, 5);
15237}
15238
15239struct Struct_array_3_f32 {
15240 float a[3];
15241};
15242
15243struct Struct_array_3_f32 zig_ret_struct_array_3_f32(void);
15244void zig_struct_array_3_f32(struct Struct_array_3_f32, size_t);
15245
15246struct Struct_array_3_f32 c_ret_struct_array_3_f32(void) {
15247 return (struct Struct_array_3_f32){ .a = { 8, 9, 10 } };
15248}
15249void c_struct_array_3_f32(struct Struct_array_3_f32 s, size_t i) {
15250 assert_or_panic(s.a[0] == 11);
15251 assert_or_panic(s.a[1] == 12);
15252 assert_or_panic(s.a[2] == 13);
15253 assert_or_panic(i == 14);
15254}
15255void c_test_struct_array_3_f32(void) {
15256 struct Struct_array_3_f32 s = zig_ret_struct_array_3_f32();
15257 assert_or_panic(s.a[0] == 1);
15258 assert_or_panic(s.a[1] == 2);
15259 assert_or_panic(s.a[2] == 3);
15260 zig_struct_array_3_f32((struct Struct_array_3_f32){ .a = { 4, 5, 6 } }, 7);
15261}
15262
15263struct Struct_array_4_f32 {
15264 float a[4];
15265};
15266
15267struct Struct_array_4_f32 zig_ret_struct_array_4_f32(void);
15268void zig_struct_array_4_f32(struct Struct_array_4_f32, size_t);
15269
15270struct Struct_array_4_f32 c_ret_struct_array_4_f32(void) {
15271 return (struct Struct_array_4_f32){ .a = { 10, 11, 12, 13 } };
15272}
15273void c_struct_array_4_f32(struct Struct_array_4_f32 s, size_t i) {
15274 assert_or_panic(s.a[0] == 14);
15275 assert_or_panic(s.a[1] == 15);
15276 assert_or_panic(s.a[2] == 16);
15277 assert_or_panic(s.a[3] == 17);
15278 assert_or_panic(i == 18);
15279}
15280void c_test_struct_array_4_f32(void) {
15281 struct Struct_array_4_f32 s = zig_ret_struct_array_4_f32();
15282 assert_or_panic(s.a[0] == 1);
15283 assert_or_panic(s.a[1] == 2);
15284 assert_or_panic(s.a[2] == 3);
15285 assert_or_panic(s.a[3] == 4);
15286 zig_struct_array_4_f32((struct Struct_array_4_f32){ .a = { 5, 6, 7, 8 } }, 9);
15287}
15288
15289struct Struct_array_5_f32 {
15290 float a[5];
15291};
15292
15293struct Struct_array_5_f32 zig_ret_struct_array_5_f32(void);
15294void zig_struct_array_5_f32(struct Struct_array_5_f32, size_t);
15295
15296struct Struct_array_5_f32 c_ret_struct_array_5_f32(void) {
15297 return (struct Struct_array_5_f32){ .a = { 12, 13, 14, 15, 16 } };
15298}
15299void c_struct_array_5_f32(struct Struct_array_5_f32 s, size_t i) {
15300 assert_or_panic(s.a[0] == 17);
15301 assert_or_panic(s.a[1] == 18);
15302 assert_or_panic(s.a[2] == 19);
15303 assert_or_panic(s.a[3] == 20);
15304 assert_or_panic(s.a[4] == 21);
15305 assert_or_panic(i == 22);
15306}
15307void c_test_struct_array_5_f32(void) {
15308 struct Struct_array_5_f32 s = zig_ret_struct_array_5_f32();
15309 assert_or_panic(s.a[0] == 1);
15310 assert_or_panic(s.a[1] == 2);
15311 assert_or_panic(s.a[2] == 3);
15312 assert_or_panic(s.a[3] == 4);
15313 assert_or_panic(s.a[4] == 5);
15314 zig_struct_array_5_f32((struct Struct_array_5_f32){ .a = { 6, 7, 8, 9, 10 } }, 11);
15315}
15316
1518915317struct Struct_f32a8 {
1519015318 alignas(8) float a;
1519115319};
......@@ -15401,6 +15529,126 @@ void c_test_struct_f64_f64_f64_f64_f64(void) {
1540115529 zig_struct_f64_f64_f64_f64_f64((struct Struct_f64_f64_f64_f64_f64){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11);
1540215530}
1540315531
15532struct Struct_array_1_f64 {
15533 double a[1];
15534};
15535
15536struct Struct_array_1_f64 zig_ret_struct_array_1_f64(void);
15537void zig_struct_array_1_f64(struct Struct_array_1_f64, size_t);
15538
15539struct Struct_array_1_f64 c_ret_struct_array_1_f64(void) {
15540 return (struct Struct_array_1_f64){ .a = { 4 } };
15541}
15542void c_struct_array_1_f64(struct Struct_array_1_f64 s, size_t i) {
15543 assert_or_panic(s.a[0] == 5);
15544 assert_or_panic(i == 6);
15545}
15546void c_test_struct_array_1_f64(void) {
15547 struct Struct_array_1_f64 s = zig_ret_struct_array_1_f64();
15548 assert_or_panic(s.a[0] == 1);
15549 zig_struct_array_1_f64((struct Struct_array_1_f64){ .a = { 2 } }, 3);
15550}
15551
15552struct Struct_array_2_f64 {
15553 double a[2];
15554};
15555
15556struct Struct_array_2_f64 zig_ret_struct_array_2_f64(void);
15557void zig_struct_array_2_f64(struct Struct_array_2_f64, size_t);
15558
15559struct Struct_array_2_f64 c_ret_struct_array_2_f64(void) {
15560 return (struct Struct_array_2_f64){ .a = { 6, 7 } };
15561}
15562void c_struct_array_2_f64(struct Struct_array_2_f64 s, size_t i) {
15563 assert_or_panic(s.a[0] == 8);
15564 assert_or_panic(s.a[1] == 9);
15565 assert_or_panic(i == 10);
15566}
15567void c_test_struct_array_2_f64(void) {
15568 struct Struct_array_2_f64 s = zig_ret_struct_array_2_f64();
15569 assert_or_panic(s.a[0] == 1);
15570 assert_or_panic(s.a[1] == 2);
15571 zig_struct_array_2_f64((struct Struct_array_2_f64){ .a = { 3, 4 } }, 5);
15572}
15573
15574struct Struct_array_3_f64 {
15575 double a[3];
15576};
15577
15578struct Struct_array_3_f64 zig_ret_struct_array_3_f64(void);
15579void zig_struct_array_3_f64(struct Struct_array_3_f64, size_t);
15580
15581struct Struct_array_3_f64 c_ret_struct_array_3_f64(void) {
15582 return (struct Struct_array_3_f64){ .a = { 8, 9, 10 } };
15583}
15584void c_struct_array_3_f64(struct Struct_array_3_f64 s, size_t i) {
15585 assert_or_panic(s.a[0] == 11);
15586 assert_or_panic(s.a[1] == 12);
15587 assert_or_panic(s.a[2] == 13);
15588 assert_or_panic(i == 14);
15589}
15590void c_test_struct_array_3_f64(void) {
15591 struct Struct_array_3_f64 s = zig_ret_struct_array_3_f64();
15592 assert_or_panic(s.a[0] == 1);
15593 assert_or_panic(s.a[1] == 2);
15594 assert_or_panic(s.a[2] == 3);
15595 zig_struct_array_3_f64((struct Struct_array_3_f64){ .a = { 4, 5, 6 } }, 7);
15596}
15597
15598struct Struct_array_4_f64 {
15599 double a[4];
15600};
15601
15602struct Struct_array_4_f64 zig_ret_struct_array_4_f64(void);
15603void zig_struct_array_4_f64(struct Struct_array_4_f64, size_t);
15604
15605struct Struct_array_4_f64 c_ret_struct_array_4_f64(void) {
15606 return (struct Struct_array_4_f64){ .a = { 10, 11, 12, 13 } };
15607}
15608void c_struct_array_4_f64(struct Struct_array_4_f64 s, size_t i) {
15609 assert_or_panic(s.a[0] == 14);
15610 assert_or_panic(s.a[1] == 15);
15611 assert_or_panic(s.a[2] == 16);
15612 assert_or_panic(s.a[3] == 17);
15613 assert_or_panic(i == 18);
15614}
15615void c_test_struct_array_4_f64(void) {
15616 struct Struct_array_4_f64 s = zig_ret_struct_array_4_f64();
15617 assert_or_panic(s.a[0] == 1);
15618 assert_or_panic(s.a[1] == 2);
15619 assert_or_panic(s.a[2] == 3);
15620 assert_or_panic(s.a[3] == 4);
15621 zig_struct_array_4_f64((struct Struct_array_4_f64){ .a = { 5, 6, 7, 8 } }, 9);
15622}
15623
15624struct Struct_array_5_f64 {
15625 double a[5];
15626};
15627
15628struct Struct_array_5_f64 zig_ret_struct_array_5_f64(void);
15629void zig_struct_array_5_f64(struct Struct_array_5_f64, size_t);
15630
15631struct Struct_array_5_f64 c_ret_struct_array_5_f64(void) {
15632 return (struct Struct_array_5_f64){ .a = { 12, 13, 14, 15, 16 } };
15633}
15634void c_struct_array_5_f64(struct Struct_array_5_f64 s, size_t i) {
15635 assert_or_panic(s.a[0] == 17);
15636 assert_or_panic(s.a[1] == 18);
15637 assert_or_panic(s.a[2] == 19);
15638 assert_or_panic(s.a[3] == 20);
15639 assert_or_panic(s.a[4] == 21);
15640 assert_or_panic(i == 22);
15641}
15642void c_test_struct_array_5_f64(void) {
15643 struct Struct_array_5_f64 s = zig_ret_struct_array_5_f64();
15644 assert_or_panic(s.a[0] == 1);
15645 assert_or_panic(s.a[1] == 2);
15646 assert_or_panic(s.a[2] == 3);
15647 assert_or_panic(s.a[3] == 4);
15648 assert_or_panic(s.a[4] == 5);
15649 zig_struct_array_5_f64((struct Struct_array_5_f64){ .a = { 6, 7, 8, 9, 10 } }, 11);
15650}
15651
1540415652struct Struct_u32_Union_u32_u32u32 {
1540515653 uint32_t a;
1540615654 union {
......@@ -15563,8 +15811,7 @@ void run_c_tests(void) {
1556315811#if !(defined(__i386__) && defined(_WIN32))
1556415812#ifndef __loongarch__
1556515813#ifndef ZIG_MIPS64
15566#ifndef __powerpc__
15567#ifndef __s390x__
15814#ifndef ZIG_PPC32
1556815815 {
1556915816 struct Struct_i32_i32 s = {1, 2};
1557015817 zig_struct_i32_i32(s);
......@@ -15573,13 +15820,11 @@ void run_c_tests(void) {
1557315820#endif
1557415821#endif
1557515822#endif
15576#endif
1557715823
1557815824#ifndef __hexagon__
1557915825#ifndef __loongarch__
1558015826#ifndef ZIG_MIPS64
15581#ifndef __powerpc__
15582#ifndef __s390x__
15827#ifndef ZIG_PPC32
1558315828 {
1558415829 struct BigStruct s = {1, 2, 3, 4, 5};
1558515830 zig_big_struct(s);
......@@ -15588,7 +15833,6 @@ void run_c_tests(void) {
1558815833#endif
1558915834#endif
1559015835#endif
15591#endif
1559215836
1559315837#ifndef ZIG_NO_I128
1559415838 {
......@@ -15612,8 +15856,7 @@ void run_c_tests(void) {
1561215856#ifndef __i386__
1561315857#ifndef __loongarch__
1561415858#ifndef ZIG_MIPS64
15615#ifndef __powerpc__
15616#ifndef __s390x__
15859#ifndef ZIG_PPC32
1561715860 {
1561815861 struct SplitStructInts s = {1234, 100, 1337};
1561915862 zig_split_struct_ints(s);
......@@ -15623,13 +15866,11 @@ void run_c_tests(void) {
1562315866#endif
1562415867#endif
1562515868#endif
15626#endif
1562715869
1562815870#ifndef __hexagon__
1562915871#ifndef __loongarch__
1563015872#ifndef ZIG_MIPS64
15631#ifndef __powerpc__
15632#ifndef __s390x__
15873#ifndef ZIG_PPC32
1563315874 {
1563415875 struct MedStructMixed s = {1234, 100.0f, 1337.0f};
1563515876 zig_med_struct_mixed(s);
......@@ -15638,14 +15879,12 @@ void run_c_tests(void) {
1563815879#endif
1563915880#endif
1564015881#endif
15641#endif
1564215882
1564315883#ifndef __hexagon__
1564415884#ifndef __i386__
1564515885#ifndef __loongarch__
1564615886#ifndef ZIG_MIPS64
15647#ifndef __powerpc__
15648#ifndef __s390x__
15887#ifndef ZIG_PPC32
1564915888 {
1565015889 struct SplitStructMixed s = {1234, 100, 1337.0f};
1565115890 zig_split_struct_mixed(s);
......@@ -15655,13 +15894,11 @@ void run_c_tests(void) {
1565515894#endif
1565615895#endif
1565715896#endif
15658#endif
1565915897
1566015898#ifndef __hexagon__
1566115899#ifndef __loongarch__
1566215900#ifndef ZIG_MIPS64
15663#ifndef __powerpc__
15664#ifndef __s390x__
15901#ifndef ZIG_PPC32
1566515902 {
1566615903 struct BigStruct s = {30, 31, 32, 33, 34};
1566715904 struct BigStruct res = zig_big_struct_both(s);
......@@ -15674,7 +15911,6 @@ void run_c_tests(void) {
1567415911#endif
1567515912#endif
1567615913#endif
15677#endif
1567815914#endif
1567915915
1568015916 {
test/c_abi/main.zig+558-246
......@@ -13,7 +13,7 @@ const expectEqual = std.testing.expectEqual;
1313const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and
1414 !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and
1515 builtin.cpu.arch != .hexagon and
16 builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460
16 builtin.cpu.arch != .s390x;
1717
1818const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc);
1919const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc;
......@@ -161,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;
161161extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;
162162
163163const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and
164 !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC32() and !builtin.cpu.arch.isRISCV() and
164 !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC() and !builtin.cpu.arch.isRISCV() and
165165 builtin.cpu.arch != .hexagon and
166166 builtin.cpu.arch != .s390x and
167167 !(builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft);
......@@ -451,8 +451,11 @@ test "long double" {
451451
452452comptime {
453453 skip: {
454 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
455 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
454 if (builtin.cpu.arch == .hexagon) break :skip;
455 if (builtin.cpu.arch == .loongarch64) break :skip;
456 if (builtin.cpu.arch.isMIPS()) break :skip;
457 if (builtin.cpu.arch.isPowerPC64()) break :skip;
458 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
456459
457460 _ = struct {
458461 export fn zig_ret_vector_2_bool() @Vector(2, bool) {
......@@ -474,7 +477,13 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void;
474477extern fn c_test_vector_2_bool() void;
475478
476479test "@Vector(2, bool)" {
477 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
480 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
481 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
482 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
483 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
484 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
485 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
486 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
478487
479488 const vec = c_ret_vector_2_bool();
480489 try expect(vec[0] == true);
......@@ -488,8 +497,11 @@ test "@Vector(2, bool)" {
488497
489498comptime {
490499 skip: {
491 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
492 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
500 if (builtin.cpu.arch == .hexagon) break :skip;
501 if (builtin.cpu.arch == .loongarch64) break :skip;
502 if (builtin.cpu.arch.isMIPS()) break :skip;
503 if (builtin.cpu.arch.isPowerPC64()) break :skip;
504 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
493505
494506 _ = struct {
495507 export fn zig_ret_vector_4_bool() @Vector(4, bool) {
......@@ -515,7 +527,13 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void;
515527extern fn c_test_vector_4_bool() void;
516528
517529test "@Vector(4, bool)" {
518 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
530 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
531 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
532 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
533 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
534 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
535 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
536 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
519537
520538 const vec = c_ret_vector_4_bool();
521539 try expect(vec[0] == true);
......@@ -533,8 +551,11 @@ test "@Vector(4, bool)" {
533551
534552comptime {
535553 skip: {
536 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
537 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
554 if (builtin.cpu.arch == .hexagon) break :skip;
555 if (builtin.cpu.arch == .loongarch64) break :skip;
556 if (builtin.cpu.arch.isMIPS()) break :skip;
557 if (builtin.cpu.arch.isPowerPC64()) break :skip;
558 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
538559
539560 _ = struct {
540561 export fn zig_ret_vector_8_bool() @Vector(8, bool) {
......@@ -568,7 +589,13 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void;
568589extern fn c_test_vector_8_bool() void;
569590
570591test "@Vector(8, bool)" {
571 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
592 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
593 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
594 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
595 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
596 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
597 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
598 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
572599
573600 const vec = c_ret_vector_8_bool();
574601 try expect(vec[0] == false);
......@@ -594,8 +621,11 @@ test "@Vector(8, bool)" {
594621
595622comptime {
596623 skip: {
597 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
598 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
624 if (builtin.cpu.arch == .hexagon) break :skip;
625 if (builtin.cpu.arch == .loongarch64) break :skip;
626 if (builtin.cpu.arch.isMIPS()) break :skip;
627 if (builtin.cpu.arch.isPowerPC64()) break :skip;
628 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
599629
600630 _ = struct {
601631 export fn zig_ret_vector_16_bool() @Vector(16, bool) {
......@@ -645,7 +675,13 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void;
645675extern fn c_test_vector_16_bool() void;
646676
647677test "@Vector(16, bool)" {
648 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
678 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
679 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
680 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
681 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
682 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
683 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
684 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
649685
650686 const vec = c_ret_vector_16_bool();
651687 try expect(vec[0] == true);
......@@ -687,8 +723,11 @@ test "@Vector(16, bool)" {
687723
688724comptime {
689725 skip: {
690 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
691 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
726 if (builtin.cpu.arch == .hexagon) break :skip;
727 if (builtin.cpu.arch == .loongarch64) break :skip;
728 if (builtin.cpu.arch.isMIPS()) break :skip;
729 if (builtin.cpu.arch.isPowerPC64()) break :skip;
730 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
692731
693732 _ = struct {
694733 export fn zig_ret_vector_32_bool() @Vector(32, bool) {
......@@ -770,7 +809,13 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void;
770809extern fn c_test_vector_32_bool() void;
771810
772811test "@Vector(32, bool)" {
773 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
812 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
813 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
814 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
815 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
816 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
817 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
818 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
774819
775820 const vec = c_ret_vector_32_bool();
776821 try expect(vec[0] == true);
......@@ -844,8 +889,11 @@ test "@Vector(32, bool)" {
844889
845890comptime {
846891 skip: {
847 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
848 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
892 if (builtin.cpu.arch == .hexagon) break :skip;
893 if (builtin.cpu.arch == .loongarch64) break :skip;
894 if (builtin.cpu.arch.isMIPS()) break :skip;
895 if (builtin.cpu.arch.isPowerPC64()) break :skip;
896 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
849897
850898 _ = struct {
851899 export fn zig_ret_vector_64_bool() @Vector(64, bool) {
......@@ -991,7 +1039,11 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void;
9911039extern fn c_test_vector_64_bool() void;
9921040
9931041test "@Vector(64, bool)" {
994 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
1042 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1043 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1044 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1045 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
1046 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
9951047
9961048 const vec = c_ret_vector_64_bool();
9971049 try expect(vec[0] == false);
......@@ -1129,8 +1181,11 @@ test "@Vector(64, bool)" {
11291181
11301182comptime {
11311183 skip: {
1132 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
1133 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
1184 if (builtin.cpu.arch == .hexagon) break :skip;
1185 if (builtin.cpu.arch == .loongarch64) break :skip;
1186 if (builtin.cpu.arch.isMIPS()) break :skip;
1187 if (builtin.cpu.arch.isPowerPC64()) break :skip;
1188 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
11341189
11351190 _ = struct {
11361191 export fn zig_ret_vector_128_bool() @Vector(128, bool) {
......@@ -1404,7 +1459,11 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void;
14041459extern fn c_test_vector_128_bool() void;
14051460
14061461test "@Vector(128, bool)" {
1407 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
1462 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1463 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1464 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1465 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
1466 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
14081467
14091468 const vec = c_ret_vector_128_bool();
14101469 try expect(vec[0] == false);
......@@ -1670,8 +1729,11 @@ test "@Vector(128, bool)" {
16701729
16711730comptime {
16721731 skip: {
1673 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
1674 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
1732 if (builtin.cpu.arch == .hexagon) break :skip;
1733 if (builtin.cpu.arch == .loongarch64) break :skip;
1734 if (builtin.cpu.arch.isMIPS()) break :skip;
1735 if (builtin.cpu.arch.isPowerPC64()) break :skip;
1736 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
16751737
16761738 _ = struct {
16771739 export fn zig_ret_vector_256_bool() @Vector(256, bool) {
......@@ -2201,7 +2263,11 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void;
22012263extern fn c_test_vector_256_bool() void;
22022264
22032265test "@Vector(256, bool)" {
2204 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
2266 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
2267 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
2268 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
2269 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
2270 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
22052271
22062272 const vec = c_ret_vector_256_bool();
22072273 try expect(vec[0] == true);
......@@ -2723,8 +2789,11 @@ test "@Vector(256, bool)" {
27232789
27242790comptime {
27252791 skip: {
2726 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
2727 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
2792 if (builtin.cpu.arch == .hexagon) break :skip;
2793 if (builtin.cpu.arch == .loongarch64) break :skip;
2794 if (builtin.cpu.arch.isMIPS()) break :skip;
2795 if (builtin.cpu.arch.isPowerPC64()) break :skip;
2796 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip;
27282797
27292798 _ = struct {
27302799 export fn zig_ret_vector_512_bool() @Vector(512, bool) {
......@@ -3766,7 +3835,11 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void;
37663835extern fn c_test_vector_512_bool() void;
37673836
37683837test "@Vector(512, bool)" {
3769 if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
3838 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
3839 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
3840 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
3841 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
3842 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
37703843
37713844 const vec = c_ret_vector_512_bool();
37723845 try expect(vec[0] == false);
......@@ -4840,7 +4913,7 @@ test "@Vector(2, u8)" {
48404913 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
48414914 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
48424915 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4843 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
4916 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
48444917
48454918 const v = c_ret_vector_2_u8();
48464919 try expect(v[0] == 9);
......@@ -4869,7 +4942,6 @@ test "@Vector(3, u8)" {
48694942 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
48704943 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
48714944 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4872 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
48734945
48744946 const v = c_ret_vector_3_u8();
48754947 try expect(v[0] == 19);
......@@ -4912,7 +4984,7 @@ test "@Vector(4, u8)" {
49124984 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
49134985 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
49144986 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4915 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
4987 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
49164988
49174989 const v = c_ret_vector_4_u8();
49184990 try expect(v[0] == 41);
......@@ -4946,7 +5018,6 @@ test "@Vector(6, u8)" {
49465018 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
49475019 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
49485020 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
4949 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
49505021
49515022 const v = c_ret_vector_6_u8();
49525023 try expect(v[0] == 53);
......@@ -5136,7 +5207,6 @@ test "@Vector(24, u8)" {
51365207 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
51375208 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
51385209 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5139 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
51405210
51415211 const v = c_ret_vector_24_u8();
51425212 try expect(v[0] == 57);
......@@ -5220,7 +5290,6 @@ test "@Vector(32, u8)" {
52205290 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
52215291 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
52225292 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5223 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
52245293
52255294 const v = c_ret_vector_32_u8();
52265295 try expect(v[0] == 69);
......@@ -5330,7 +5399,6 @@ test "@Vector(48, u8)" {
53305399 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
53315400 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
53325401 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5333 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
53345402
53355403 const v = c_ret_vector_48_u8();
53365404 try expect(v[0] == 29);
......@@ -5473,7 +5541,6 @@ test "@Vector(64, u8)" {
54735541 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
54745542 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
54755543 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5476 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
54775544
54785545 const v = c_ret_vector_64_u8();
54795546 try expect(v[0] == 53);
......@@ -5668,7 +5735,6 @@ test "@Vector(96, u8)" {
56685735 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
56695736 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
56705737 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5671 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
56725738
56735739 const v = c_ret_vector_96_u8();
56745740 try expect(v[0] == 82);
......@@ -5931,7 +5997,6 @@ test "@Vector(128, u8)" {
59315997 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
59325998 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
59335999 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
5934 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
59356000
59366001 const v = c_ret_vector_128_u8();
59376002 try expect(v[0] == 30);
......@@ -6296,7 +6361,6 @@ test "@Vector(192, u8)" {
62966361 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
62976362 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
62986363 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
6299 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
63006364
63016365 const v = c_ret_vector_192_u8();
63026366 try expect(v[0] == 70);
......@@ -6797,7 +6861,6 @@ test "@Vector(256, u8)" {
67976861 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
67986862 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
67996863 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
6800 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
68016864
68026865 const v = c_ret_vector_256_u8();
68036866 try expect(v[0] == 66);
......@@ -7502,7 +7565,6 @@ test "@Vector(384, u8)" {
75027565 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
75037566 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
75047567 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
7505 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
75067568
75077569 const v = c_ret_vector_384_u8();
75087570 try expect(v[0] == 46);
......@@ -8479,7 +8541,6 @@ test "@Vector(512, u8)" {
84798541 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
84808542 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
84818543 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
8482 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
84838544
84848545 const v = c_ret_vector_512_u8();
84858546 try expect(v[0] == 38);
......@@ -9073,7 +9134,7 @@ test "@Vector(2, u16)" {
90739134 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
90749135 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
90759136 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9076 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
9137 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
90779138
90789139 const v = c_ret_vector_2_u16();
90799140 try expect(v[0] == 9);
......@@ -9101,7 +9162,6 @@ test "@Vector(3, u16)" {
91019162 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
91029163 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
91039164 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9104 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
91059165
91069166 const v = c_ret_vector_3_u16();
91079167 try expect(v[0] == 19);
......@@ -9250,7 +9310,6 @@ test "@Vector(12, u16)" {
92509310 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
92519311 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
92529312 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9253 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
92549313
92559314 const v = c_ret_vector_12_u16();
92569315 try expect(v[0] == 121);
......@@ -9300,7 +9359,6 @@ test "@Vector(16, u16)" {
93009359 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
93019360 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
93029361 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9303 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
93049362
93059363 const v = c_ret_vector_16_u16();
93069364 try expect(v[0] == 177);
......@@ -9366,7 +9424,6 @@ test "@Vector(24, u16)" {
93669424 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
93679425 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
93689426 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9369 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
93709427
93719428 const v = c_ret_vector_24_u16();
93729429 try expect(v[0] == 257);
......@@ -9450,7 +9507,6 @@ test "@Vector(32, u16)" {
94509507 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
94519508 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
94529509 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9453 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
94549510
94559511 const v = c_ret_vector_32_u16();
94569512 try expect(v[0] == 369);
......@@ -9560,7 +9616,6 @@ test "@Vector(48, u16)" {
95609616 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
95619617 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
95629618 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9563 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
95649619
95659620 const v = c_ret_vector_48_u16();
95669621 try expect(v[0] == 529);
......@@ -9704,7 +9759,6 @@ test "@Vector(64, u16)" {
97049759 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
97059760 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
97069761 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9707 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
97089762
97099763 const v = c_ret_vector_64_u16();
97109764 try expect(v[0] == 753);
......@@ -9899,7 +9953,6 @@ test "@Vector(96, u16)" {
98999953 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
99009954 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
99019955 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
9902 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
99039956
99049957 const v = c_ret_vector_96_u16();
99059958 try expect(v[0] == 1082);
......@@ -10162,7 +10215,6 @@ test "@Vector(128, u16)" {
1016210215 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1016310216 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1016410217 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
10165 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1016610218
1016710219 const v = c_ret_vector_128_u16();
1016810220 try expect(v[0] == 1530);
......@@ -10527,7 +10579,6 @@ test "@Vector(192, u16)" {
1052710579 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1052810580 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1052910581 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
10530 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1053110582
1053210583 const v = c_ret_vector_192_u16();
1053310584 try expect(v[0] == 2170);
......@@ -11028,7 +11079,6 @@ test "@Vector(256, u16)" {
1102811079 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1102911080 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1103011081 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11031 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1103211082
1103311083 const v = c_ret_vector_256_u16();
1103411084 try expect(v[0] == 3066);
......@@ -11445,7 +11495,6 @@ test "@Vector(6, u32)" {
1144511495 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1144611496 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1144711497 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11448 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1144911498
1145011499 const v = c_ret_vector_6_u32();
1145111500 try expect(v[0] == 53);
......@@ -11481,7 +11530,6 @@ test "@Vector(8, u32)" {
1148111530 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1148211531 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1148311532 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11484 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1148511533
1148611534 const v = c_ret_vector_8_u32();
1148711535 try expect(v[0] == 81);
......@@ -11524,7 +11572,6 @@ test "@Vector(12, u32)" {
1152411572 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1152511573 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1152611574 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11527 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1152811575
1152911576 const v = c_ret_vector_12_u32();
1153011577 try expect(v[0] == 121);
......@@ -11574,7 +11621,6 @@ test "@Vector(16, u32)" {
1157411621 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1157511622 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1157611623 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11577 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1157811624
1157911625 const v = c_ret_vector_16_u32();
1158011626 try expect(v[0] == 177);
......@@ -11640,7 +11686,6 @@ test "@Vector(24, u32)" {
1164011686 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1164111687 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1164211688 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11643 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1164411689
1164511690 const v = c_ret_vector_24_u32();
1164611691 try expect(v[0] == 257);
......@@ -11725,7 +11770,6 @@ test "@Vector(32, u32)" {
1172511770 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1172611771 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1172711772 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11728 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1172911773
1173011774 const v = c_ret_vector_32_u32();
1173111775 try expect(v[0] == 369);
......@@ -11835,7 +11879,6 @@ test "@Vector(48, u32)" {
1183511879 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1183611880 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1183711881 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11838 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1183911882
1184011883 const v = c_ret_vector_48_u32();
1184111884 try expect(v[0] == 529);
......@@ -11979,7 +12022,6 @@ test "@Vector(64, u32)" {
1197912022 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1198012023 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1198112024 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
11982 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1198312025
1198412026 const v = c_ret_vector_64_u32();
1198512027 try expect(v[0] == 753);
......@@ -12174,7 +12216,6 @@ test "@Vector(96, u32)" {
1217412216 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1217512217 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1217612218 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12177 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1217812219
1217912220 const v = c_ret_vector_96_u32();
1218012221 try expect(v[0] == 1082);
......@@ -12437,7 +12478,6 @@ test "@Vector(128, u32)" {
1243712478 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1243812479 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1243912480 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12440 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1244112481
1244212482 const v = c_ret_vector_128_u32();
1244312483 try expect(v[0] == 1530);
......@@ -12594,8 +12634,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void;
1259412634extern fn c_test_vector_1_u64() void;
1259512635
1259612636test "@Vector(1, u64)" {
12597 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
12598
1259912637 const v = c_ret_vector_1_u64();
1260012638 try expect(v[0] == 3);
1260112639 c_vector_1_u64(.{4}, 1);
......@@ -12644,7 +12682,6 @@ test "@Vector(3, u64)" {
1264412682 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1264512683 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1264612684 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12647 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1264812685
1264912686 const v = c_ret_vector_3_u64();
1265012687 try expect(v[0] == 19);
......@@ -12673,7 +12710,6 @@ test "@Vector(4, u64)" {
1267312710 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1267412711 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1267512712 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12676 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1267712713
1267812714 const v = c_ret_vector_4_u64();
1267912715 try expect(v[0] == 33);
......@@ -12740,7 +12776,6 @@ test "@Vector(8, u64)" {
1274012776 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1274112777 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1274212778 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12743 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1274412779
1274512780 const v = c_ret_vector_8_u64();
1274612781 try expect(v[0] == 81);
......@@ -12832,7 +12867,6 @@ test "@Vector(16, u64)" {
1283212867 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1283312868 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1283412869 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12835 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1283612870
1283712871 const v = c_ret_vector_16_u64();
1283812872 try expect(v[0] == 177);
......@@ -12981,7 +13015,6 @@ test "@Vector(32, u64)" {
1298113015 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1298213016 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1298313017 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
12984 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1298513018
1298613019 const v = c_ret_vector_32_u64();
1298713020 try expect(v[0] == 369);
......@@ -13233,7 +13266,6 @@ test "@Vector(64, u64)" {
1323313266 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1323413267 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1323513268 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13236 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1323713269
1323813270 const v = c_ret_vector_64_u64();
1323913271 try expect(v[0] == 753);
......@@ -13327,7 +13359,6 @@ test "@Vector(1, f32)" {
1332713359 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1332813360 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1332913361 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13330 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
1333113362
1333213363 const v = c_ret_vector_1_f32();
1333313364 try expect(v[0] == 3);
......@@ -13449,7 +13480,6 @@ test "@Vector(6, f32)" {
1344913480 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1345013481 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1345113482 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13452 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1345313483
1345413484 const v = c_ret_vector_6_f32();
1345513485 try expect(v[0] == 53);
......@@ -13486,7 +13516,6 @@ test "@Vector(8, f32)" {
1348613516 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1348713517 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1348813518 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13489 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1349013519
1349113520 const v = c_ret_vector_8_f32();
1349213521 try expect(v[0] == 81);
......@@ -13529,7 +13558,6 @@ test "@Vector(12, f32)" {
1352913558 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1353013559 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1353113560 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13532 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1353313561
1353413562 const v = c_ret_vector_12_f32();
1353513563 try expect(v[0] == 121);
......@@ -13580,7 +13608,6 @@ test "@Vector(16, f32)" {
1358013608 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1358113609 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1358213610 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13583 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1358413611
1358513612 const v = c_ret_vector_16_f32();
1358613613 try expect(v[0] == 177);
......@@ -13646,7 +13673,6 @@ test "@Vector(24, f32)" {
1364613673 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1364713674 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1364813675 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13649 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1365013676
1365113677 const v = c_ret_vector_24_f32();
1365213678 try expect(v[0] == 257);
......@@ -13731,7 +13757,6 @@ test "@Vector(32, f32)" {
1373113757 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1373213758 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1373313759 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13734 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1373513760
1373613761 const v = c_ret_vector_32_f32();
1373713762 try expect(v[0] == 369);
......@@ -13841,7 +13866,6 @@ test "@Vector(48, f32)" {
1384113866 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1384213867 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1384313868 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13844 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1384513869
1384613870 const v = c_ret_vector_48_f32();
1384713871 try expect(v[0] == 529);
......@@ -13985,7 +14009,6 @@ test "@Vector(64, f32)" {
1398514009 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1398614010 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1398714011 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
13988 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1398914012
1399014013 const v = c_ret_vector_64_f32();
1399114014 try expect(v[0] == 753);
......@@ -14180,7 +14203,6 @@ test "@Vector(96, f32)" {
1418014203 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1418114204 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1418214205 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14183 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1418414206
1418514207 const v = c_ret_vector_96_f32();
1418614208 try expect(v[0] == 1082);
......@@ -14443,7 +14465,6 @@ test "@Vector(128, f32)" {
1444314465 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1444414466 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1444514467 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14446 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1444714468
1444814469 const v = c_ret_vector_128_f32();
1444914470 try expect(v[0] == 1530);
......@@ -14651,7 +14672,6 @@ test "@Vector(3, f64)" {
1465114672 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1465214673 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1465314674 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14654 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1465514675
1465614676 const v = c_ret_vector_3_f64();
1465714677 try expect(v[0] == 19);
......@@ -14680,8 +14700,6 @@ test "@Vector(4, f64)" {
1468014700 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1468114701 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1468214702 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14683 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
14684 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899
1468514703
1468614704 const v = c_ret_vector_4_f64();
1468714705 try expect(v[0] == 33);
......@@ -14714,7 +14732,6 @@ test "@Vector(6, f64)" {
1471414732 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1471514733 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1471614734 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14717 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1471814735
1471914736 const v = c_ret_vector_6_f64();
1472014737 try expect(v[0] == 53);
......@@ -14750,8 +14767,6 @@ test "@Vector(8, f64)" {
1475014767 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1475114768 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1475214769 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14753 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
14754 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899
1475514770
1475614771 const v = c_ret_vector_8_f64();
1475714772 try expect(v[0] == 81);
......@@ -14794,7 +14809,6 @@ test "@Vector(12, f64)" {
1479414809 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1479514810 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1479614811 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14797 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1479814812
1479914813 const v = c_ret_vector_12_f64();
1480014814 try expect(v[0] == 121);
......@@ -14845,7 +14859,6 @@ test "@Vector(16, f64)" {
1484514859 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1484614860 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1484714861 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14848 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1484914862
1485014863 const v = c_ret_vector_16_f64();
1485114864 try expect(v[0] == 177);
......@@ -14911,7 +14924,6 @@ test "@Vector(24, f64)" {
1491114924 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1491214925 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1491314926 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14914 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1491514927
1491614928 const v = c_ret_vector_24_f64();
1491714929 try expect(v[0] == 257);
......@@ -14996,7 +15008,6 @@ test "@Vector(32, f64)" {
1499615008 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1499715009 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1499815010 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
14999 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1500015011
1500115012 const v = c_ret_vector_32_f64();
1500215013 try expect(v[0] == 369);
......@@ -15106,7 +15117,6 @@ test "@Vector(48, f64)" {
1510615117 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1510715118 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1510815119 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
15109 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1511015120
1511115121 const v = c_ret_vector_48_f64();
1511215122 try expect(v[0] == 529);
......@@ -15250,7 +15260,6 @@ test "@Vector(64, f64)" {
1525015260 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1525115261 if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
1525215262 if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
15253 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1525415263
1525515264 const v = c_ret_vector_64_f64();
1525615265 try expect(v[0] == 753);
......@@ -15345,7 +15354,6 @@ extern fn c_test_struct_u8() void;
1534515354test "struct u8" {
1534615355 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1534715356 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15348 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1534915357 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1535015358
1535115359 const s = c_ret_struct_u8();
......@@ -15376,8 +15384,7 @@ test "struct u8, u8" {
1537615384 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1537715385 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1537815386 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15379 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15380 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15387 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1538115388 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1538215389
1538315390 const s = c_ret_struct_u8_u8();
......@@ -15411,8 +15418,7 @@ test "struct u8, u8, u8" {
1541115418 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1541215419 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1541315420 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15414 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15415 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15421 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1541615422 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1541715423
1541815424 const s = c_ret_struct_u8_u8_u8();
......@@ -15449,8 +15455,7 @@ test "struct u8, u8, u8, u8" {
1544915455 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1545015456 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1545115457 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15452 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15453 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15458 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1545415459 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1545515460
1545615461 const s = c_ret_struct_u8_u8_u8_u8();
......@@ -15481,7 +15486,6 @@ extern fn c_test_struct_u16() void;
1548115486test "struct u16" {
1548215487 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1548315488 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15484 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1548515489 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1548615490
1548715491 const s = c_ret_struct_u16();
......@@ -15512,8 +15516,7 @@ test "struct u16, u16" {
1551215516 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1551315517 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1551415518 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15515 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15516 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15519 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1551715520 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1551815521
1551915522 const s = c_ret_struct_u16_u16();
......@@ -15547,9 +15550,8 @@ test "struct u16, u16, u16" {
1554715550 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1554815551 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1554915552 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15550 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15553 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1555115554 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15552 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1555315555 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1555415556
1555515557 const s = c_ret_struct_u16_u16_u16();
......@@ -15586,9 +15588,8 @@ test "struct u16, u16, u16, u16" {
1558615588 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1558715589 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1558815590 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15589 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15591 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1559015592 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15591 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1559215593 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1559315594
1559415595 const s = c_ret_struct_u16_u16_u16_u16();
......@@ -15619,7 +15620,6 @@ extern fn c_test_struct_u32() void;
1561915620test "struct u32" {
1562015621 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1562115622 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15622 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1562315623 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1562415624
1562515625 const s = c_ret_struct_u32();
......@@ -15649,9 +15649,8 @@ extern fn c_test_struct_u32_u32() void;
1564915649test "struct u32, u32" {
1565015650 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1565115651 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15652 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15652 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1565315653 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15654 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1565515654 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1565615655
1565715656 const s = c_ret_struct_u32_u32();
......@@ -15685,8 +15684,7 @@ test "struct u32, u32, u32" {
1568515684 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1568615685 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1568715686 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15688 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15689 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15687 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1569015688
1569115689 const s = c_ret_struct_u32_u32_u32();
1569215690 try expect(s.a == 8);
......@@ -15722,8 +15720,7 @@ test "struct u32, u32, u32, u32" {
1572215720 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1572315721 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1572415722 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15725 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15726 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15723 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1572715724
1572815725 const s = c_ret_struct_u32_u32_u32_u32();
1572915726 try expect(s.a == 10);
......@@ -15753,7 +15750,6 @@ extern fn c_test_struct_u64() void;
1575315750test "struct u64" {
1575415751 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1575515752 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15756 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1575715753 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1575815754
1575915755 const s = c_ret_struct_u64();
......@@ -15831,7 +15827,6 @@ extern fn c_test_struct_u64_u64() void;
1583115827test "struct u64, u64" {
1583215828 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1583315829 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15834 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1583515830
1583615831 const s = c_ret_struct_u64_u64();
1583715832 try expect(s.a == 21);
......@@ -15871,8 +15866,7 @@ extern fn c_test_struct_u64_u64_u64() void;
1587115866test "struct u64, u64, u64" {
1587215867 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1587315868 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15874 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15875 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15869 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1587615870
1587715871 const s = c_ret_struct_u64_u64_u64();
1587815872 try expect(s.a == 8);
......@@ -15907,8 +15901,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void;
1590715901test "struct u64, u64, u64, u64" {
1590815902 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1590915903 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
15910 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
15911 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15904 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1591215905
1591315906 const s = c_ret_struct_u64_u64_u64_u64();
1591415907 try expect(s.a == 10);
......@@ -15937,8 +15930,7 @@ extern fn c_test_struct_f32() void;
1593715930
1593815931test "struct f32" {
1593915932 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
15940 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
15941 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
15933 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1594215934 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1594315935
1594415936 const s = c_ret_struct_f32();
......@@ -15971,7 +15963,6 @@ test "struct f32, f32" {
1597115963 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1597215964 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1597315965 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
15974 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1597515966 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1597615967
1597715968 const s = c_ret_struct_f32_f32();
......@@ -16007,7 +15998,6 @@ test "struct f32, f32, f32" {
1600715998 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1600815999 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1600916000 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16010 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1601116001
1601216002 const s = c_ret_struct_f32_f32_f32();
1601316003 try expect(s.a == 8);
......@@ -16045,7 +16035,6 @@ test "struct f32, f32, f32, f32" {
1604516035 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1604616036 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1604716037 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16048 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1604916038
1605016039 const s = c_ret_struct_f32_f32_f32_f32();
1605116040 try expect(s.a == 10);
......@@ -16085,7 +16074,6 @@ test "struct f32, f32, f32, f32, f32" {
1608516074 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1608616075 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1608716076 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16088 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1608916077
1609016078 const s = c_ret_struct_f32_f32_f32_f32_f32();
1609116079 try expect(s.a == 12);
......@@ -16097,6 +16085,181 @@ test "struct f32, f32, f32, f32, f32" {
1609716085 c_test_struct_f32_f32_f32_f32_f32();
1609816086}
1609916087
16088const Struct_array_1_f32 = extern struct {
16089 a: [1]f32,
16090};
16091
16092comptime {
16093 skip: {
16094 if (builtin.cpu.arch.isWasm()) break :skip;
16095
16096 _ = struct {
16097 export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 {
16098 return .{ .a = .{1} };
16099 }
16100 export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void {
16101 expect(s.a[0] == 2) catch @panic("test failure");
16102 expect(i == 3) catch @panic("test failure");
16103 }
16104 };
16105 }
16106}
16107
16108extern fn c_ret_struct_array_1_f32() Struct_array_1_f32;
16109extern fn c_struct_array_1_f32(Struct_array_1_f32, usize) void;
16110extern fn c_test_struct_array_1_f32() void;
16111
16112test "struct [1]f32" {
16113 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16114 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16115 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16116 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16117 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16118 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16119 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
16120
16121 const s = c_ret_struct_array_1_f32();
16122 try expect(s.a[0] == 4);
16123 c_struct_array_1_f32(.{ .a = .{5} }, 6);
16124 c_test_struct_array_1_f32();
16125}
16126
16127const Struct_array_2_f32 = extern struct {
16128 a: [2]f32,
16129};
16130
16131export fn zig_ret_struct_array_2_f32() Struct_array_2_f32 {
16132 return .{ .a = .{ 1, 2 } };
16133}
16134export fn zig_struct_array_2_f32(s: Struct_array_2_f32, i: usize) void {
16135 expect(s.a[0] == 3) catch @panic("test failure");
16136 expect(s.a[1] == 4) catch @panic("test failure");
16137 expect(i == 5) catch @panic("test failure");
16138}
16139
16140extern fn c_ret_struct_array_2_f32() Struct_array_2_f32;
16141extern fn c_struct_array_2_f32(Struct_array_2_f32, usize) void;
16142extern fn c_test_struct_array_2_f32() void;
16143
16144test "struct [2]f32" {
16145 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16146 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16147 if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
16148 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16149 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16150 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16151
16152 const s = c_ret_struct_array_2_f32();
16153 try expect(s.a[0] == 6);
16154 try expect(s.a[1] == 7);
16155 c_struct_array_2_f32(.{ .a = .{ 8, 9 } }, 10);
16156 c_test_struct_array_2_f32();
16157}
16158
16159const Struct_array_3_f32 = extern struct {
16160 a: [3]f32,
16161};
16162
16163export fn zig_ret_struct_array_3_f32() Struct_array_3_f32 {
16164 return .{ .a = .{ 1, 2, 3 } };
16165}
16166export fn zig_struct_array_3_f32(s: Struct_array_3_f32, i: usize) void {
16167 expect(s.a[0] == 4) catch @panic("test failure");
16168 expect(s.a[1] == 5) catch @panic("test failure");
16169 expect(s.a[2] == 6) catch @panic("test failure");
16170 expect(i == 7) catch @panic("test failure");
16171}
16172
16173extern fn c_ret_struct_array_3_f32() Struct_array_3_f32;
16174extern fn c_struct_array_3_f32(Struct_array_3_f32, usize) void;
16175extern fn c_test_struct_array_3_f32() void;
16176
16177test "struct [3]f32" {
16178 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16179 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16180 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16181 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16182 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16183
16184 const s = c_ret_struct_array_3_f32();
16185 try expect(s.a[0] == 8);
16186 try expect(s.a[1] == 9);
16187 try expect(s.a[2] == 10);
16188 c_struct_array_3_f32(.{ .a = .{ 11, 12, 13 } }, 14);
16189 c_test_struct_array_3_f32();
16190}
16191
16192const Struct_array_4_f32 = extern struct {
16193 a: [4]f32,
16194};
16195
16196export fn zig_ret_struct_array_4_f32() Struct_array_4_f32 {
16197 return .{ .a = .{ 1, 2, 3, 4 } };
16198}
16199export fn zig_struct_array_4_f32(s: Struct_array_4_f32, i: usize) void {
16200 expect(s.a[0] == 5) catch @panic("test failure");
16201 expect(s.a[1] == 6) catch @panic("test failure");
16202 expect(s.a[2] == 7) catch @panic("test failure");
16203 expect(s.a[3] == 8) catch @panic("test failure");
16204 expect(i == 9) catch @panic("test failure");
16205}
16206
16207extern fn c_ret_struct_array_4_f32() Struct_array_4_f32;
16208extern fn c_struct_array_4_f32(Struct_array_4_f32, usize) void;
16209extern fn c_test_struct_array_4_f32() void;
16210
16211test "struct [4]f32" {
16212 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16213 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16214 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16215 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16216 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16217
16218 const s = c_ret_struct_array_4_f32();
16219 try expect(s.a[0] == 10);
16220 try expect(s.a[1] == 11);
16221 try expect(s.a[2] == 12);
16222 try expect(s.a[3] == 13);
16223 c_struct_array_4_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18);
16224 c_test_struct_array_4_f32();
16225}
16226
16227const Struct_array_5_f32 = extern struct {
16228 a: [5]f32,
16229};
16230
16231export fn zig_ret_struct_array_5_f32() Struct_array_5_f32 {
16232 return .{ .a = .{ 1, 2, 3, 4, 5 } };
16233}
16234export fn zig_struct_array_5_f32(s: Struct_array_5_f32, i: usize) void {
16235 expect(s.a[0] == 6) catch @panic("test failure");
16236 expect(s.a[1] == 7) catch @panic("test failure");
16237 expect(s.a[2] == 8) catch @panic("test failure");
16238 expect(s.a[3] == 9) catch @panic("test failure");
16239 expect(s.a[4] == 10) catch @panic("test failure");
16240 expect(i == 11) catch @panic("test failure");
16241}
16242
16243extern fn c_ret_struct_array_5_f32() Struct_array_5_f32;
16244extern fn c_struct_array_5_f32(Struct_array_5_f32, usize) void;
16245extern fn c_test_struct_array_5_f32() void;
16246
16247test "struct [5]f32" {
16248 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16249 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16250 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16251 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16252
16253 const s = c_ret_struct_array_5_f32();
16254 try expect(s.a[0] == 12);
16255 try expect(s.a[1] == 13);
16256 try expect(s.a[2] == 14);
16257 try expect(s.a[3] == 15);
16258 try expect(s.a[4] == 16);
16259 c_struct_array_5_f32(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22);
16260 c_test_struct_array_5_f32();
16261}
16262
1610016263const Struct_f32a8 = extern struct {
1610116264 a: f32 align(8),
1610216265};
......@@ -16120,7 +16283,6 @@ test "struct f32 align(8)" {
1612016283 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1612116284 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1612216285 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16123 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1612416286 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1612516287
1612616288 const s = c_ret_struct_f32a8();
......@@ -16154,7 +16316,6 @@ test "struct f32 align(8), f32 align(8)" {
1615416316 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1615516317 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1615616318 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16157 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1615816319 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1615916320
1616016321 const s = c_ret_struct_f32a8_f32a8();
......@@ -16187,8 +16348,7 @@ test "struct {f32, f32}, f32" {
1618716348 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1618816349 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1618916350 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16190 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16191 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16351 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1619216352
1619316353 const s = c_ret_struct_f32f32_f32();
1619416354 try expect(s.a.b == 1.0);
......@@ -16221,8 +16381,7 @@ test "struct f32, {f32, f32}" {
1622116381 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1622216382 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1622316383 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16224 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16225 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16384 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1622616385
1622716386 const s = c_ret_struct_f32_f32f32();
1622816387 try expect(s.a == 1.0);
......@@ -16250,9 +16409,8 @@ extern fn c_test_struct_f64() void;
1625016409
1625116410test "struct f64" {
1625216411 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
16253 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16412 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1625416413 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16255 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1625616414 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1625716415
1625816416 const s = c_ret_struct_f64();
......@@ -16282,8 +16440,7 @@ extern fn c_test_struct_f64_f64() void;
1628216440test "struct f64, f64" {
1628316441 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
1628416442 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16285 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16286 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16443 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1628716444
1628816445 const s = c_ret_struct_f64_f64();
1628916446 try expect(s.a == 6);
......@@ -16315,8 +16472,7 @@ extern fn c_test_struct_f64_f64_f64() void;
1631516472test "struct f64, f64, f64" {
1631616473 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1631716474 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16318 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16319 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16475 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1632016476
1632116477 const s = c_ret_struct_f64_f64_f64();
1632216478 try expect(s.a == 8);
......@@ -16351,8 +16507,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void;
1635116507test "struct f64, f64, f64, f64" {
1635216508 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1635316509 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16354 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16355 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16510 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1635616511
1635716512 const s = c_ret_struct_f64_f64_f64_f64();
1635816513 try expect(s.a == 10);
......@@ -16390,8 +16545,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void;
1639016545test "struct f64, f64, f64, f64, f64" {
1639116546 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1639216547 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
16393 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16394 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16548 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1639516549
1639616550 const s = c_ret_struct_f64_f64_f64_f64_f64();
1639716551 try expect(s.a == 12);
......@@ -16403,6 +16557,181 @@ test "struct f64, f64, f64, f64, f64" {
1640316557 c_test_struct_f64_f64_f64_f64_f64();
1640416558}
1640516559
16560const Struct_array_1_f64 = extern struct {
16561 a: [1]f64,
16562};
16563
16564comptime {
16565 skip: {
16566 if (builtin.cpu.arch.isWasm()) break :skip;
16567
16568 _ = struct {
16569 export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 {
16570 return .{ .a = .{1} };
16571 }
16572 export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void {
16573 expect(s.a[0] == 2) catch @panic("test failure");
16574 expect(i == 3) catch @panic("test failure");
16575 }
16576 };
16577 }
16578}
16579
16580extern fn c_ret_struct_array_1_f64() Struct_array_1_f64;
16581extern fn c_struct_array_1_f64(Struct_array_1_f64, usize) void;
16582extern fn c_test_struct_array_1_f64() void;
16583
16584test "struct [1]f64" {
16585 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16586 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16587 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16588 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16589 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16590 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16591 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
16592
16593 const s = c_ret_struct_array_1_f64();
16594 try expect(s.a[0] == 4);
16595 c_struct_array_1_f64(.{ .a = .{5} }, 6);
16596 c_test_struct_array_1_f64();
16597}
16598
16599const Struct_array_2_f64 = extern struct {
16600 a: [2]f64,
16601};
16602
16603export fn zig_ret_struct_array_2_f64() Struct_array_2_f64 {
16604 return .{ .a = .{ 1, 2 } };
16605}
16606export fn zig_struct_array_2_f64(s: Struct_array_2_f64, i: usize) void {
16607 expect(s.a[0] == 3) catch @panic("test failure");
16608 expect(s.a[1] == 4) catch @panic("test failure");
16609 expect(i == 5) catch @panic("test failure");
16610}
16611
16612extern fn c_ret_struct_array_2_f64() Struct_array_2_f64;
16613extern fn c_struct_array_2_f64(Struct_array_2_f64, usize) void;
16614extern fn c_test_struct_array_2_f64() void;
16615
16616test "struct [2]f64" {
16617 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16618 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16619 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16620 if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
16621 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16622 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16623 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16624
16625 const s = c_ret_struct_array_2_f64();
16626 try expect(s.a[0] == 6);
16627 try expect(s.a[1] == 7);
16628 c_struct_array_2_f64(.{ .a = .{ 8, 9 } }, 10);
16629 c_test_struct_array_2_f64();
16630}
16631
16632const Struct_array_3_f64 = extern struct {
16633 a: [3]f64,
16634};
16635
16636export fn zig_ret_struct_array_3_f64() Struct_array_3_f64 {
16637 return .{ .a = .{ 1, 2, 3 } };
16638}
16639export fn zig_struct_array_3_f64(s: Struct_array_3_f64, i: usize) void {
16640 expect(s.a[0] == 4) catch @panic("test failure");
16641 expect(s.a[1] == 5) catch @panic("test failure");
16642 expect(s.a[2] == 6) catch @panic("test failure");
16643 expect(i == 7) catch @panic("test failure");
16644}
16645
16646extern fn c_ret_struct_array_3_f64() Struct_array_3_f64;
16647extern fn c_struct_array_3_f64(Struct_array_3_f64, usize) void;
16648extern fn c_test_struct_array_3_f64() void;
16649
16650test "struct [3]f64" {
16651 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16652 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16653 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16654 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16655 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16656
16657 const s = c_ret_struct_array_3_f64();
16658 try expect(s.a[0] == 8);
16659 try expect(s.a[1] == 9);
16660 try expect(s.a[2] == 10);
16661 c_struct_array_3_f64(.{ .a = .{ 11, 12, 13 } }, 14);
16662 c_test_struct_array_3_f64();
16663}
16664
16665const Struct_array_4_f64 = extern struct {
16666 a: [4]f64,
16667};
16668
16669export fn zig_ret_struct_array_4_f64() Struct_array_4_f64 {
16670 return .{ .a = .{ 1, 2, 3, 4 } };
16671}
16672export fn zig_struct_array_4_f64(s: Struct_array_4_f64, i: usize) void {
16673 expect(s.a[0] == 5) catch @panic("test failure");
16674 expect(s.a[1] == 6) catch @panic("test failure");
16675 expect(s.a[2] == 7) catch @panic("test failure");
16676 expect(s.a[3] == 8) catch @panic("test failure");
16677 expect(i == 9) catch @panic("test failure");
16678}
16679
16680extern fn c_ret_struct_array_4_f64() Struct_array_4_f64;
16681extern fn c_struct_array_4_f64(Struct_array_4_f64, usize) void;
16682extern fn c_test_struct_array_4_f64() void;
16683
16684test "struct [4]f64" {
16685 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16686 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16687 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16688 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16689 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16690
16691 const s = c_ret_struct_array_4_f64();
16692 try expect(s.a[0] == 10);
16693 try expect(s.a[1] == 11);
16694 try expect(s.a[2] == 12);
16695 try expect(s.a[3] == 13);
16696 c_struct_array_4_f64(.{ .a = .{ 14, 15, 16, 17 } }, 18);
16697 c_test_struct_array_4_f64();
16698}
16699
16700const Struct_array_5_f64 = extern struct {
16701 a: [5]f64,
16702};
16703
16704export fn zig_ret_struct_array_5_f64() Struct_array_5_f64 {
16705 return .{ .a = .{ 1, 2, 3, 4, 5 } };
16706}
16707export fn zig_struct_array_5_f64(s: Struct_array_5_f64, i: usize) void {
16708 expect(s.a[0] == 6) catch @panic("test failure");
16709 expect(s.a[1] == 7) catch @panic("test failure");
16710 expect(s.a[2] == 8) catch @panic("test failure");
16711 expect(s.a[3] == 9) catch @panic("test failure");
16712 expect(s.a[4] == 10) catch @panic("test failure");
16713 expect(i == 11) catch @panic("test failure");
16714}
16715
16716extern fn c_ret_struct_array_5_f64() Struct_array_5_f64;
16717extern fn c_struct_array_5_f64(Struct_array_5_f64, usize) void;
16718extern fn c_test_struct_array_5_f64() void;
16719
16720test "struct [5]f64" {
16721 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16722 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16723 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16724
16725 const s = c_ret_struct_array_5_f64();
16726 try expect(s.a[0] == 12);
16727 try expect(s.a[1] == 13);
16728 try expect(s.a[2] == 14);
16729 try expect(s.a[3] == 15);
16730 try expect(s.a[4] == 16);
16731 c_struct_array_5_f64(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22);
16732 c_test_struct_array_5_f64();
16733}
16734
1640616735const Struct_u32_Union_u32_u32u32 = extern struct {
1640716736 a: u32,
1640816737 b: extern union {
......@@ -16430,8 +16759,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" {
1643016759 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1643116760 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
1643216761 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16433 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16434 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16762 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1643516763
1643616764 const s = c_ret_struct_u32_union_u32_u32u32();
1643716765 try expect(s.a == 1);
......@@ -16449,11 +16777,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32;
1644916777extern fn c_struct_i32_i32(Struct_i32_i32) void;
1645016778
1645116779test "struct i32 i32" {
16780 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1645216781 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16453 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16782 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1645416783 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16455 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16456 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1645716784 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1645816785
1645916786 const s: Struct_i32_i32 = .{
......@@ -16483,11 +16810,10 @@ const BigStruct = extern struct {
1648316810extern fn c_big_struct(BigStruct) void;
1648416811
1648516812test "big struct" {
16486 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16487 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16488 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1648916813 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16490 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16814 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16815 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16816 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1649116817
1649216818 const s = BigStruct{
1649316819 .a = 1,
......@@ -16513,10 +16839,9 @@ const BigUnion = extern union {
1651316839extern fn c_big_union(BigUnion) void;
1651416840
1651516841test "big union" {
16516 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16517 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1651816842 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16519 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16843 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16844 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1652016845
1652116846 const x = BigUnion{
1652216847 .a = BigStruct{
......@@ -16548,11 +16873,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
1654816873extern fn c_ret_med_struct_mixed() MedStructMixed;
1654916874
1655016875test "medium struct of ints and floats" {
16551 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16552 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16553 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1655416876 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16555 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16877 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16878 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16879 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1655616880
1655716881 const s = MedStructMixed{
1655816882 .a = 1234,
......@@ -16628,12 +16952,11 @@ const SplitStructInt = extern struct {
1662816952extern fn c_split_struct_ints(SplitStructInt) void;
1662916953
1663016954test "split struct of ints" {
16631 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16632 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16633 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16634 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1663516955 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16636 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16956 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16957 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16958 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16959 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1663716960
1663816961 const s = SplitStructInt{
1663916962 .a = 1234,
......@@ -16658,12 +16981,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
1665816981extern fn c_ret_split_struct_mixed() SplitStructMixed;
1665916982
1666016983test "split struct of ints and floats" {
16661 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16662 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16663 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16664 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1666516984 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16666 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16985 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16986 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16987 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16988 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1666716989
1666816990 const s = SplitStructMixed{
1666916991 .a = 1234,
......@@ -16686,11 +17008,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void {
1668617008extern fn c_big_struct_both(BigStruct) BigStruct;
1668717009
1668817010test "sret and byval together" {
16689 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16690 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16691 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1669217011 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16693 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17012 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17013 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17014 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1669417015
1669517016 const s = BigStruct{
1669617017 .a = 1,
......@@ -16800,12 +17121,11 @@ extern fn c_struct_with_array(StructWithArray) void;
1680017121extern fn c_ret_struct_with_array() StructWithArray;
1680117122
1680217123test "Struct with array as padding." {
16803 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
16804 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16805 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16806 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1680717124 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16808 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17125 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17126 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17127 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17128 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
1680917129
1681017130 c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
1681117131
......@@ -16829,11 +17149,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void;
1682917149extern fn c_ret_float_array_struct() FloatArrayStruct;
1683017150
1683117151test "Float array like struct" {
16832 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16833 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
16834 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1683517152 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16836 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17153 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17154 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17155 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1683717156
1683817157 c_float_array_struct(.{
1683917158 .origin = .{
......@@ -16864,37 +17183,37 @@ pub inline fn expectOk(c_err: c_int) !void {
1686417183/// Tests for Double + Char struct
1686517184const DC = extern struct { v1: f64, v2: u8 };
1686617185test "DC: Zig passes to C" {
17186 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17187 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1686717188 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17189 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1686817190 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16869 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16870 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16871 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16872 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17191
1687317192 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
1687417193}
1687517194test "DC: Zig returns to C" {
17195 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1687617196 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17197 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1687717198 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16878 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16879 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16880 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17199
1688117200 try expectOk(c_assert_ret_DC());
1688217201}
1688317202test "DC: C passes to Zig" {
17203 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17204 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1688417205 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17206 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1688517207 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16886 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16887 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16888 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16889 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17208
1689017209 try expectOk(c_send_DC());
1689117210}
1689217211test "DC: C returns to Zig" {
17212 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1689317213 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17214 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1689417215 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16895 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16896 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16897 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17216
1689817217 try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC());
1689917218}
1690017219
......@@ -16919,36 +17238,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
1691917238test "CFF: Zig passes to C" {
1692017239 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1692117240 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16922 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17241 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1692317242 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1692417243 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16925 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17244
1692617245 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
1692717246}
1692817247test "CFF: Zig returns to C" {
1692917248 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16930 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17249 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1693117250 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16932 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17251
1693317252 try expectOk(c_assert_ret_CFF());
1693417253}
1693517254test "CFF: C passes to Zig" {
16936 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
16937 if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest;
16938 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16939 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16940 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1694117255 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16942 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17256 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17257 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17258 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17259 if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest;
17260 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1694317261
1694417262 try expectOk(c_send_CFF());
1694517263}
1694617264test "CFF: C returns to Zig" {
16947 if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest;
16948 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16949 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1695017265 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16951 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17266 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17267 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17268 if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest;
17269
1695217270 try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF());
1695317271}
1695417272pub extern fn c_assert_CFF(lv: CFF) c_int;
......@@ -16971,35 +17289,35 @@ pub export fn zig_ret_CFF() CFF {
1697117289const PD = extern struct { v1: ?*anyopaque, v2: f64 };
1697217290
1697317291test "PD: Zig passes to C" {
16974 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16975 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16976 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1697717292 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16978 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17293 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17294 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17295 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1697917296 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
17297
1698017298 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
1698117299}
1698217300test "PD: Zig returns to C" {
16983 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16984 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1698517301 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
16986 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17302 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17303 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17304
1698717305 try expectOk(c_assert_ret_PD());
1698817306}
1698917307test "PD: C passes to Zig" {
16990 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16991 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16992 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1699317308 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16994 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17309 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17310 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17311 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1699517312 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
17313
1699617314 try expectOk(c_send_PD());
1699717315}
1699817316test "PD: C returns to Zig" {
16999 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17000 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1700117317 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17002 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17318 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17319 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17320
1700317321 try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD());
1700417322}
1700517323pub extern fn c_assert_PD(lv: PD) c_int;
......@@ -17033,7 +17351,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef;
1703317351test "C function modifies by ref param" {
1703417352 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1703517353 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17036 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1703717354
1703817355 const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined });
1703917356 try expect(res.val == 42);
......@@ -17054,11 +17371,10 @@ const ByVal = extern struct {
1705417371
1705517372extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void;
1705617373test "C function that takes byval struct called via function pointer" {
17374 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17375 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1705717376 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1705817377 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17059 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17060 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17061 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1706217378
1706317379 var fn_ptr = &c_func_ptr_byval;
1706417380 _ = &fn_ptr;
......@@ -17077,17 +17393,16 @@ test "C function that takes byval struct called via function pointer" {
1707717393
1707817394extern fn c_f16(f16) f16;
1707917395test "f16 bare" {
17080 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;
17081 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
17396 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
1708217397 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
1708317398 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1708417399 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
17400 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1708517401 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
1708617402 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1708717403 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
17088 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17089
17090 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
17404 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
17405 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;
1709117406
1709217407 const a = c_f16(12);
1709317408 try expect(a == 34);
......@@ -17098,9 +17413,9 @@ const f16_struct = extern struct {
1709817413};
1709917414extern fn c_f16_struct(f16_struct) f16_struct;
1710017415test "f16 struct" {
17416 if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest;
1710117417 if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest;
1710217418 if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17103 if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest;
1710417419 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1710517420 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1710617421
......@@ -17207,11 +17522,10 @@ const Coord2 = extern struct {
1720717522
1720817523extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2;
1720917524test "Stdcall ABI structs" {
17525 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17526 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1721017527 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1721117528 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
17212 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17213 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17214 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
1721517529 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
1721617530
1721717531 const res = stdcall_coord2(
......@@ -17225,10 +17539,9 @@ test "Stdcall ABI structs" {
1722517539
1722617540extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void;
1722717541test "Stdcall ABI big union" {
17228 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17229 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1723017542 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17231 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17543 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17544 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
1723217545
1723317546 const x = BigUnion{
1723417547 .a = BigStruct{
......@@ -17300,11 +17613,10 @@ const byval_tail_callsite_attr = struct {
1730017613};
1730117614
1730217615test "byval tail callsite attribute" {
17303 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17304 if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
17305 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
1730617616 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
17307 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
17617 if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
17618 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
17619 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1730817620
1730917621 // Originally reported at https://github.com/ziglang/zig/issues/16290
1731017622 // the bug was that the extern function had the byval attribute, but
test/standalone/build.zig-1
......@@ -39,7 +39,6 @@ pub fn build(b: *std.Build) void {
3939 "../../tools/gen_parser_oracle.zig",
4040 "../../tools/gen_spirv_spec.zig",
4141 "../../tools/gen_stubs.zig",
42 "../../tools/generate_c_size_and_align_checks.zig",
4342 "../../tools/generate_JSONTestSuite.zig",
4443 "../../tools/generate_linux_syscalls.zig",
4544 "../../tools/process_headers.zig",
test/tests.zig+54-16
......@@ -274,6 +274,15 @@ const module_test_targets = blk: {
274274 },
275275 .link_libc = true,
276276 },
277 .{
278 .target = .{
279 .cpu_arch = .arm,
280 .os_tag = .linux,
281 .abi = .musleabi,
282 .ofmt = .c,
283 },
284 .link_libc = true,
285 },
277286 .{
278287 .target = .{
279288 .cpu_arch = .arm,
......@@ -292,6 +301,15 @@ const module_test_targets = blk: {
292301 },
293302 .link_libc = true,
294303 },
304 .{
305 .target = .{
306 .cpu_arch = .arm,
307 .os_tag = .linux,
308 .abi = .musleabihf,
309 .ofmt = .c,
310 },
311 .link_libc = true,
312 },
295313 .{
296314 .target = .{
297315 .cpu_arch = .arm,
......@@ -341,6 +359,15 @@ const module_test_targets = blk: {
341359 },
342360 .link_libc = true,
343361 },
362 .{
363 .target = .{
364 .cpu_arch = .armeb,
365 .os_tag = .linux,
366 .abi = .musleabi,
367 .ofmt = .c,
368 },
369 .link_libc = true,
370 },
344371 // Crashes in weird ways when applying relocations.
345372 // .{
346373 // .target = .{
......@@ -360,6 +387,15 @@ const module_test_targets = blk: {
360387 },
361388 .link_libc = true,
362389 },
390 .{
391 .target = .{
392 .cpu_arch = .armeb,
393 .os_tag = .linux,
394 .abi = .musleabihf,
395 .ofmt = .c,
396 },
397 .link_libc = true,
398 },
363399 // Crashes in weird ways when applying relocations.
364400 // .{
365401 // .target = .{
......@@ -1107,6 +1143,15 @@ const module_test_targets = blk: {
11071143 },
11081144 .link_libc = true,
11091145 },
1146 .{
1147 .target = .{
1148 .cpu_arch = .x86,
1149 .os_tag = .linux,
1150 .abi = .musl,
1151 .ofmt = .c,
1152 },
1153 .link_libc = true,
1154 },
11101155 .{
11111156 .target = .{
11121157 .cpu_arch = .x86,
......@@ -1645,6 +1690,15 @@ const module_test_targets = blk: {
16451690 },
16461691 .link_libc = true,
16471692 },
1693 .{
1694 .target = .{
1695 .cpu_arch = .x86,
1696 .os_tag = .windows,
1697 .abi = .gnu,
1698 .ofmt = .c,
1699 },
1700 .link_libc = true,
1701 },
16481702
16491703 .{
16501704 .target = .{
......@@ -1961,7 +2015,6 @@ const c_abi_targets = blk: {
19612015 .abi = .musl,
19622016 },
19632017 .use_llvm = false,
1964 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
19652018 },
19662019 .{
19672020 .target = .{
......@@ -1972,7 +2025,6 @@ const c_abi_targets = blk: {
19722025 },
19732026 .use_llvm = false,
19742027 .strip = true,
1975 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
19762028 },
19772029 .{
19782030 .target = .{
......@@ -1983,7 +2035,6 @@ const c_abi_targets = blk: {
19832035 },
19842036 .use_llvm = false,
19852037 .pic = true,
1986 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
19872038 },
19882039 .{
19892040 .target = .{
......@@ -2028,7 +2079,6 @@ const c_abi_targets = blk: {
20282079 .abi = .gnu,
20292080 },
20302081 .use_llvm = false,
2031 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
20322082 },
20332083 .{
20342084 .target = .{
......@@ -2038,7 +2088,6 @@ const c_abi_targets = blk: {
20382088 .abi = .gnu,
20392089 },
20402090 .use_llvm = false,
2041 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
20422091 },
20432092 .{
20442093 .target = .{
......@@ -2048,7 +2097,6 @@ const c_abi_targets = blk: {
20482097 .abi = .gnu,
20492098 },
20502099 .use_llvm = false,
2051 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
20522100 },
20532101 .{
20542102 .target = .{
......@@ -2782,16 +2830,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
27822830
27832831 const target = &resolved_target.result;
27842832
2785 if (target.cpu.arch == .s390x and target.ofmt == .c) {
2786 // https://codeberg.org/ziglang/zig/issues/35523
2787 continue;
2788 }
2789
2790 if (target.cpu.arch == .riscv64 and target.ofmt == .c) {
2791 // https://codeberg.org/ziglang/zig/issues/30930
2792 continue;
2793 }
2794
27952833 if (std.mem.eql(u8, options.name, "libc")) {
27962834 // The libc API tests obviously need to link libc. So for test
27972835 // target entries where we wouldn't link libc by default, skip the
tools/generate_c_size_and_align_checks.zig deleted-62
......@@ -1,62 +0,0 @@
1//! Usage: zig run tools/generate_c_size_and_align_checks.zig -- [target_triple]
2//! e.g. zig run tools/generate_c_size_and_align_checks.zig -- x86_64-linux-gnu
3//!
4//! Prints _Static_asserts for the size and alignment of all the basic built-in C
5//! types. The output can be run through a compiler for the specified target to
6//! verify that Zig's values are the same as those used by a C compiler for the
7//! target.
8
9const std = @import("std");
10const Io = std.Io;
11
12fn cName(ty: std.Target.CType) []const u8 {
13 return switch (ty) {
14 .char => "char",
15 .short => "short",
16 .ushort => "unsigned short",
17 .int => "int",
18 .uint => "unsigned int",
19 .long => "long",
20 .ulong => "unsigned long",
21 .longlong => "long long",
22 .ulonglong => "unsigned long long",
23 .float => "float",
24 .double => "double",
25 .longdouble => "long double",
26 };
27}
28
29var general_purpose_allocator: std.heap.DebugAllocator(.{}) = .init;
30
31pub fn main(init: std.process.Init) !void {
32 const args = try init.minimal.args.toSlice(init.arena.allocator());
33 const io = init.io;
34
35 if (args.len != 2) {
36 std.debug.print("Usage: {s} [target_triple]\n", .{args[0]});
37 std.process.exit(1);
38 }
39
40 const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] });
41 const target = try std.zig.system.resolveTargetQuery(io, query);
42
43 var buffer: [2000]u8 = undefined;
44 var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer);
45 const w = &stdout_writer.interface;
46 inline for (@typeInfo(std.Target.CType).@"enum".field_values) |field_value| {
47 const c_type: std.Target.CType = @fromBackingInt(@intCast(field_value));
48 try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{
49 cName(c_type),
50 target.cTypeByteSize(c_type),
51 });
52 try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{
53 cName(c_type),
54 target.cTypeAlignment(c_type),
55 });
56 try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{
57 cName(c_type),
58 target.cTypePreferredAlignment(c_type),
59 });
60 }
61 try w.flush();
62}