authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-14 12:38:56-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-14 12:38:56-04:00
log5919b10048be6efa8c0ca6bcb259706098b2d5ec
tree307c504b85c9aee16602e667db1a5db5c25e1fff
parentcb3b1dd6ddee65d1811fb4058b5cc0f2c06d0139
parentb2a1b4c085b93d508c51307f40444252b8cd4d52
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11155 from ziglang/stage2-float-fixes

stage2 float fixes

13 files changed, 394 insertions(+), 128 deletions(-)

doc/langref.html.in+36-31
...@@ -2515,13 +2515,14 @@ test "null terminated array" {...@@ -2515,13 +2515,14 @@ test "null terminated array" {
25152515
2516 {#header_open|Vectors#}2516 {#header_open|Vectors#}
2517 <p>2517 <p>
2518 A vector is a group of booleans, {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on2518 A vector is a group of booleans, {#link|Integers#}, {#link|Floats#}, or
2519 in parallel using SIMD instructions. Vector types are created with the builtin function {#link|@Type#},2519 {#link|Pointers#} which are operated on in parallel, using SIMD instructions if possible.
2520 or using the shorthand function {#syntax#}std.meta.Vector{#endsyntax#}.2520 Vector types are created with the builtin function {#link|@Vector#}.
2521 </p>2521 </p>
2522 <p>2522 <p>
2523 Vectors support the same builtin operators as their underlying base types. These operations are performed2523 Vectors support the same builtin operators as their underlying base types.
2524 element-wise, and return a vector of the same length as the input vectors. This includes:2524 These operations are performed element-wise, and return a vector of the same length
2525 as the input vectors. This includes:
2525 </p>2526 </p>
2526 <ul>2527 <ul>
2527 <li>Arithmetic ({#syntax#}+{#endsyntax#}, {#syntax#}-{#endsyntax#}, {#syntax#}/{#endsyntax#}, {#syntax#}*{#endsyntax#},2528 <li>Arithmetic ({#syntax#}+{#endsyntax#}, {#syntax#}-{#endsyntax#}, {#syntax#}/{#endsyntax#}, {#syntax#}*{#endsyntax#},
...@@ -2532,10 +2533,11 @@ test "null terminated array" {...@@ -2532,10 +2533,11 @@ test "null terminated array" {
2532 <li>Comparison operators ({#syntax#}<{#endsyntax#}, {#syntax#}>{#endsyntax#}, {#syntax#}=={#endsyntax#}, etc.)</li>2533 <li>Comparison operators ({#syntax#}<{#endsyntax#}, {#syntax#}>{#endsyntax#}, {#syntax#}=={#endsyntax#}, etc.)</li>
2533 </ul>2534 </ul>
2534 <p>2535 <p>
2535 It is prohibited to use a math operator on a mixture of scalars (individual numbers) and vectors.2536 It is prohibited to use a math operator on a mixture of scalars (individual numbers)
2536 Zig provides the {#link|@splat#} builtin to easily convert from scalars to vectors, and it supports {#link|@reduce#}2537 and vectors. Zig provides the {#link|@splat#} builtin to easily convert from scalars
2537 and array indexing syntax to convert from vectors to scalars. Vectors also support assignment to and from2538 to vectors, and it supports {#link|@reduce#} and array indexing syntax to convert
2538 fixed-length arrays with comptime known length.2539 from vectors to scalars. Vectors also support assignment to and from fixed-length
2540 arrays with comptime known length.
2539 </p>2541 </p>
2540 <p>2542 <p>
2541 For rearranging elements within and between vectors, Zig provides the {#link|@shuffle#} and {#link|@select#} functions.2543 For rearranging elements within and between vectors, Zig provides the {#link|@shuffle#} and {#link|@select#} functions.
...@@ -2550,16 +2552,14 @@ test "null terminated array" {...@@ -2550,16 +2552,14 @@ test "null terminated array" {
2550 </p>2552 </p>
2551 {#code_begin|test|vector_example#}2553 {#code_begin|test|vector_example#}
2552const std = @import("std");2554const std = @import("std");
2553const Vector = std.meta.Vector;
2554const expectEqual = std.testing.expectEqual;2555const expectEqual = std.testing.expectEqual;
25552556
2556test "Basic vector usage" {2557test "Basic vector usage" {
2557 // Vectors have a compile-time known length and base type,2558 // Vectors have a compile-time known length and base type.
2558 // and can be assigned to using array literal syntax2559 const a = @Vector(4, i32){ 1, 2, 3, 4 };
2559 const a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };2560 const b = @Vector(4, i32){ 5, 6, 7, 8 };
2560 const b: Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
25612561
2562 // Math operations take place element-wise2562 // Math operations take place element-wise.
2563 const c = a + b;2563 const c = a + b;
25642564
2565 // Individual vector elements can be accessed using array indexing syntax.2565 // Individual vector elements can be accessed using array indexing syntax.
...@@ -2572,19 +2572,19 @@ test "Basic vector usage" {...@@ -2572,19 +2572,19 @@ test "Basic vector usage" {
2572test "Conversion between vectors, arrays, and slices" {2572test "Conversion between vectors, arrays, and slices" {
2573 // Vectors and fixed-length arrays can be automatically assigned back and forth2573 // Vectors and fixed-length arrays can be automatically assigned back and forth
2574 var arr1: [4]f32 = [_]f32{ 1.1, 3.2, 4.5, 5.6 };2574 var arr1: [4]f32 = [_]f32{ 1.1, 3.2, 4.5, 5.6 };
2575 var vec: Vector(4, f32) = arr1;2575 var vec: @Vector(4, f32) = arr1;
2576 var arr2: [4]f32 = vec;2576 var arr2: [4]f32 = vec;
2577 try expectEqual(arr1, arr2);2577 try expectEqual(arr1, arr2);
25782578
2579 // You can also assign from a slice with comptime-known length to a vector using .*2579 // You can also assign from a slice with comptime-known length to a vector using .*
2580 const vec2: Vector(2, f32) = arr1[1..3].*;2580 const vec2: @Vector(2, f32) = arr1[1..3].*;
25812581
2582 var slice: []const f32 = &arr1;2582 var slice: []const f32 = &arr1;
2583 var offset: u32 = 1;2583 var offset: u32 = 1;
2584 // To extract a comptime-known length from a runtime-known offset,2584 // To extract a comptime-known length from a runtime-known offset,
2585 // first extract a new slice from the starting offset, then an array of2585 // first extract a new slice from the starting offset, then an array of
2586 // comptime known length2586 // comptime known length
2587 const vec3: Vector(2, f32) = slice[offset..][0..2].*;2587 const vec3: @Vector(2, f32) = slice[offset..][0..2].*;
2588 try expectEqual(slice[offset], vec2[0]);2588 try expectEqual(slice[offset], vec2[0]);
2589 try expectEqual(slice[offset + 1], vec2[1]);2589 try expectEqual(slice[offset + 1], vec2[1]);
2590 try expectEqual(vec2, vec3);2590 try expectEqual(vec2, vec3);
...@@ -9084,7 +9084,7 @@ pub const PrefetchOptions = struct {...@@ -9084,7 +9084,7 @@ pub const PrefetchOptions = struct {
9084 {#header_close#}9084 {#header_close#}
90859085
9086 {#header_open|@select#}9086 {#header_open|@select#}
9087 <pre>{#syntax#}@select(comptime T: type, pred: std.meta.Vector(len, bool), a: std.meta.Vector(len, T), b: std.meta.Vector(len, T)) std.meta.Vector(len, T){#endsyntax#}</pre>9087 <pre>{#syntax#}@select(comptime T: type, pred: @Vector(len, bool), a: @Vector(len, T), b: @Vector(len, T)) @Vector(len, T){#endsyntax#}</pre>
9088 <p>9088 <p>
9089 Selects values element-wise from {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} based on {#syntax#}pred{#endsyntax#}. If {#syntax#}pred[i]{#endsyntax#} is {#syntax#}true{#endsyntax#}, the corresponding element in the result will be {#syntax#}a[i]{#endsyntax#} and otherwise {#syntax#}b[i]{#endsyntax#}.9089 Selects values element-wise from {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} based on {#syntax#}pred{#endsyntax#}. If {#syntax#}pred[i]{#endsyntax#} is {#syntax#}true{#endsyntax#}, the corresponding element in the result will be {#syntax#}a[i]{#endsyntax#} and otherwise {#syntax#}b[i]{#endsyntax#}.
9090 </p>9090 </p>
...@@ -9252,7 +9252,7 @@ test "@setRuntimeSafety" {...@@ -9252,7 +9252,7 @@ test "@setRuntimeSafety" {
9252 {#header_close#}9252 {#header_close#}
92539253
9254 {#header_open|@shuffle#}9254 {#header_open|@shuffle#}
9255 <pre>{#syntax#}@shuffle(comptime E: type, a: std.meta.Vector(a_len, E), b: std.meta.Vector(b_len, E), comptime mask: std.meta.Vector(mask_len, i32)) std.meta.Vector(mask_len, E){#endsyntax#}</pre>9255 <pre>{#syntax#}@shuffle(comptime E: type, a: @Vector(a_len, E), b: @Vector(b_len, E), comptime mask: @Vector(mask_len, i32)) @Vector(mask_len, E){#endsyntax#}</pre>
9256 <p>9256 <p>
9257 Constructs a new {#link|vector|Vectors#} by selecting elements from {#syntax#}a{#endsyntax#} and9257 Constructs a new {#link|vector|Vectors#} by selecting elements from {#syntax#}a{#endsyntax#} and
9258 {#syntax#}b{#endsyntax#} based on {#syntax#}mask{#endsyntax#}.9258 {#syntax#}b{#endsyntax#} based on {#syntax#}mask{#endsyntax#}.
...@@ -9287,22 +9287,21 @@ test "@setRuntimeSafety" {...@@ -9287,22 +9287,21 @@ test "@setRuntimeSafety" {
9287 </p>9287 </p>
9288 {#code_begin|test|vector_shuffle#}9288 {#code_begin|test|vector_shuffle#}
9289const std = @import("std");9289const std = @import("std");
9290const Vector = std.meta.Vector;
9291const expect = std.testing.expect;9290const expect = std.testing.expect;
92929291
9293test "vector @shuffle" {9292test "vector @shuffle" {
9294 const a: Vector(7, u8) = [_]u8{ 'o', 'l', 'h', 'e', 'r', 'z', 'w' };9293 const a = @Vector(7, u8){ 'o', 'l', 'h', 'e', 'r', 'z', 'w' };
9295 const b: Vector(4, u8) = [_]u8{ 'w', 'd', '!', 'x' };9294 const b = @Vector(4, u8){ 'w', 'd', '!', 'x' };
92969295
9297 // To shuffle within a single vector, pass undefined as the second argument.9296 // To shuffle within a single vector, pass undefined as the second argument.
9298 // Notice that we can re-order, duplicate, or omit elements of the input vector9297 // Notice that we can re-order, duplicate, or omit elements of the input vector
9299 const mask1: Vector(5, i32) = [_]i32{ 2, 3, 1, 1, 0 };9298 const mask1 = @Vector(5, i32){ 2, 3, 1, 1, 0 };
9300 const res1: Vector(5, u8) = @shuffle(u8, a, undefined, mask1);9299 const res1: @Vector(5, u8) = @shuffle(u8, a, undefined, mask1);
9301 try expect(std.mem.eql(u8, &@as([5]u8, res1), "hello"));9300 try expect(std.mem.eql(u8, &@as([5]u8, res1), "hello"));
93029301
9303 // Combining two vectors9302 // Combining two vectors
9304 const mask2: Vector(6, i32) = [_]i32{ -1, 0, 4, 1, -2, -3 };9303 const mask2 = @Vector(6, i32){ -1, 0, 4, 1, -2, -3 };
9305 const res2: Vector(6, u8) = @shuffle(u8, a, b, mask2);9304 const res2: @Vector(6, u8) = @shuffle(u8, a, b, mask2);
9306 try expect(std.mem.eql(u8, &@as([6]u8, res2), "world!"));9305 try expect(std.mem.eql(u8, &@as([6]u8, res2), "world!"));
9307}9306}
9308 {#code_end#}9307 {#code_end#}
...@@ -9329,7 +9328,7 @@ test "vector @shuffle" {...@@ -9329,7 +9328,7 @@ test "vector @shuffle" {
9329 {#header_close#}9328 {#header_close#}
93309329
9331 {#header_open|@splat#}9330 {#header_open|@splat#}
9332 <pre>{#syntax#}@splat(comptime len: u32, scalar: anytype) std.meta.Vector(len, @TypeOf(scalar)){#endsyntax#}</pre>9331 <pre>{#syntax#}@splat(comptime len: u32, scalar: anytype) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre>
9333 <p>9332 <p>
9334 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value9333 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
9335 {#syntax#}scalar{#endsyntax#}:9334 {#syntax#}scalar{#endsyntax#}:
...@@ -9341,7 +9340,7 @@ const expect = std.testing.expect;...@@ -9341,7 +9340,7 @@ const expect = std.testing.expect;
9341test "vector @splat" {9340test "vector @splat" {
9342 const scalar: u32 = 5;9341 const scalar: u32 = 5;
9343 const result = @splat(4, scalar);9342 const result = @splat(4, scalar);
9344 comptime try expect(@TypeOf(result) == std.meta.Vector(4, u32));9343 comptime try expect(@TypeOf(result) == @Vector(4, u32));
9345 try expect(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 }));9344 try expect(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 }));
9346}9345}
9347 {#code_end#}9346 {#code_end#}
...@@ -9381,10 +9380,10 @@ const std = @import("std");...@@ -9381,10 +9380,10 @@ const std = @import("std");
9381const expect = std.testing.expect;9380const expect = std.testing.expect;
93829381
9383test "vector @reduce" {9382test "vector @reduce" {
9384 const value: std.meta.Vector(4, i32) = [_]i32{ 1, -1, 1, -1 };9383 const value = @Vector(4, i32){ 1, -1, 1, -1 };
9385 const result = value > @splat(4, @as(i32, 0));9384 const result = value > @splat(4, @as(i32, 0));
9386 // result is { true, false, true, false };9385 // result is { true, false, true, false };
9387 comptime try expect(@TypeOf(result) == std.meta.Vector(4, bool));9386 comptime try expect(@TypeOf(result) == @Vector(4, bool));
9388 const is_all_true = @reduce(.And, result);9387 const is_all_true = @reduce(.And, result);
9389 comptime try expect(@TypeOf(is_all_true) == bool);9388 comptime try expect(@TypeOf(is_all_true) == bool);
9390 try expect(is_all_true == false);9389 try expect(is_all_true == false);
...@@ -9743,6 +9742,12 @@ fn foo(comptime T: type, ptr: *T) T {...@@ -9743,6 +9742,12 @@ fn foo(comptime T: type, ptr: *T) T {
9743 {#syntax#}@unionInit{#endsyntax#} forwards its {#link|result location|Result Location Semantics#} to {#syntax#}init_expr{#endsyntax#}.9742 {#syntax#}@unionInit{#endsyntax#} forwards its {#link|result location|Result Location Semantics#} to {#syntax#}init_expr{#endsyntax#}.
9744 </p>9743 </p>
9745 {#header_close#}9744 {#header_close#}
9745
9746
9747 {#header_open|@Vector#}
9748 <pre>{#syntax#}@Vector(len: comptime_int, Element: type) type{#endsyntax#}</pre>
9749 <p>Creates {#link|Vectors#}.</p>
9750 {#header_close#}
9746 {#header_close#}9751 {#header_close#}
97479752
9748 {#header_open|Build Mode#}9753 {#header_open|Build Mode#}
lib/std/math/round.zig+4
...@@ -20,6 +20,10 @@ pub fn round(x: anytype) @TypeOf(x) {...@@ -20,6 +20,10 @@ pub fn round(x: anytype) @TypeOf(x) {
20 f32 => round32(x),20 f32 => round32(x),
21 f64 => round64(x),21 f64 => round64(x),
22 f128 => round128(x),22 f128 => round128(x),
23
24 // TODO this is not correct for some targets
25 c_longdouble => @floatCast(c_longdouble, round128(x)),
26
23 else => @compileError("round not implemented for " ++ @typeName(T)),27 else => @compileError("round not implemented for " ++ @typeName(T)),
24 };28 };
25}29}
lib/std/meta.zig+1
...@@ -930,6 +930,7 @@ test "std.meta.Float" {...@@ -930,6 +930,7 @@ test "std.meta.Float" {
930 try testing.expectEqual(f128, Float(128));930 try testing.expectEqual(f128, Float(128));
931}931}
932932
933/// Deprecated. Use `@Vector`.
933pub fn Vector(comptime len: u32, comptime child: type) type {934pub fn Vector(comptime len: u32, comptime child: type) type {
934 return @Type(.{935 return @Type(.{
935 .Vector = .{936 .Vector = .{
lib/std/multi_array_list.zig+1-1
...@@ -421,7 +421,7 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -421,7 +421,7 @@ pub fn MultiArrayList(comptime S: type) type {
421 }421 }
422422
423 fn capacityInBytes(capacity: usize) usize {423 fn capacityInBytes(capacity: usize) usize {
424 const sizes_vector: std.meta.Vector(sizes.bytes.len, usize) = sizes.bytes;424 const sizes_vector: @Vector(sizes.bytes.len, usize) = sizes.bytes;
425 const capacity_vector = @splat(sizes.bytes.len, capacity);425 const capacity_vector = @splat(sizes.bytes.len, capacity);
426 return @reduce(.Add, capacity_vector * sizes_vector);426 return @reduce(.Add, capacity_vector * sizes_vector);
427 }427 }
lib/std/special/c.zig+9-1
...@@ -98,6 +98,7 @@ comptime {...@@ -98,6 +98,7 @@ comptime {
9898
99 @export(round, .{ .name = "round", .linkage = .Strong });99 @export(round, .{ .name = "round", .linkage = .Strong });
100 @export(roundf, .{ .name = "roundf", .linkage = .Strong });100 @export(roundf, .{ .name = "roundf", .linkage = .Strong });
101 @export(roundl, .{ .name = "roundl", .linkage = .Strong });
101102
102 @export(fmin, .{ .name = "fmin", .linkage = .Strong });103 @export(fmin, .{ .name = "fmin", .linkage = .Strong });
103 @export(fminf, .{ .name = "fminf", .linkage = .Strong });104 @export(fminf, .{ .name = "fminf", .linkage = .Strong });
...@@ -575,11 +576,18 @@ fn fabsf(a: f32) callconv(.C) f32 {...@@ -575,11 +576,18 @@ fn fabsf(a: f32) callconv(.C) f32 {
575 return math.fabs(a);576 return math.fabs(a);
576}577}
577578
579fn roundf(a: f32) callconv(.C) f32 {
580 return math.round(a);
581}
582
578fn round(a: f64) callconv(.C) f64 {583fn round(a: f64) callconv(.C) f64 {
579 return math.round(a);584 return math.round(a);
580}585}
581586
582fn roundf(a: f32) callconv(.C) f32 {587fn roundl(a: c_longdouble) callconv(.C) c_longdouble {
588 if (!long_double_is_f128) {
589 @panic("TODO implement this");
590 }
583 return math.round(a);591 return math.round(a);
584}592}
585593
src/Sema.zig+59-3
...@@ -4195,7 +4195,15 @@ fn zirDbgVar(...@@ -4195,7 +4195,15 @@ fn zirDbgVar(
4195 const str_op = sema.code.instructions.items(.data)[inst].str_op;4195 const str_op = sema.code.instructions.items(.data)[inst].str_op;
4196 const operand = sema.resolveInst(str_op.operand);4196 const operand = sema.resolveInst(str_op.operand);
4197 const operand_ty = sema.typeOf(operand);4197 const operand_ty = sema.typeOf(operand);
4198 if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty))) return;4198 switch (air_tag) {
4199 .dbg_var_ptr => {
4200 if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty.childType()))) return;
4201 },
4202 .dbg_var_val => {
4203 if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty))) return;
4204 },
4205 else => unreachable,
4206 }
4199 const name = str_op.getStr(sema.code);4207 const name = str_op.getStr(sema.code);
42004208
4201 // Add the name to the AIR.4209 // Add the name to the AIR.
...@@ -13268,7 +13276,7 @@ fn checkFloatType(...@@ -13268,7 +13276,7 @@ fn checkFloatType(
13268 ty: Type,13276 ty: Type,
13269) CompileError!void {13277) CompileError!void {
13270 switch (ty.zigTypeTag()) {13278 switch (ty.zigTypeTag()) {
13271 .ComptimeFloat, .Float => {},13279 .ComptimeInt, .ComptimeFloat, .Float => {},
13272 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty}),13280 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty}),
13273 }13281 }
13274}13282}
...@@ -17169,10 +17177,25 @@ fn storePtr2(...@@ -17169,10 +17177,25 @@ fn storePtr2(
17169 return;17177 return;
17170 }17178 }
1717117179
17180 // TODO do the same thing for anon structs as for tuples above.
17181
17182 // Detect if we are storing an array operand to a bitcasted vector pointer.
17183 // If so, we instead reach through the bitcasted pointer to the vector pointer,
17184 // bitcast the array operand to a vector, and then lower this as a store of
17185 // a vector value to a vector pointer. This generally results in better code,
17186 // as well as working around an LLVM bug:
17187 // https://github.com/ziglang/zig/issues/11154
17188 if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| {
17189 const vector_ty = sema.typeOf(vector_ptr).childType();
17190 const vector = try sema.coerce(block, vector_ty, uncasted_operand, operand_src);
17191 try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store);
17192 return;
17193 }
17194
17172 const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src);17195 const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src);
17196 const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand);
1717317197
17174 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {17198 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
17175 const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand);
17176 const operand_val = maybe_operand_val orelse {17199 const operand_val = maybe_operand_val orelse {
17177 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);17200 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
17178 break :rs operand_src;17201 break :rs operand_src;
...@@ -17195,6 +17218,39 @@ fn storePtr2(...@@ -17195,6 +17218,39 @@ fn storePtr2(
17195 _ = try block.addBinOp(air_tag, ptr, operand);17218 _ = try block.addBinOp(air_tag, ptr, operand);
17196}17219}
1719717220
17221/// Traverse an arbitrary number of bitcasted pointers and return the underyling vector
17222/// pointer. Only if the final element type matches the vector element type, and the
17223/// lengths match.
17224fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
17225 const array_ty = sema.typeOf(ptr).childType();
17226 if (array_ty.zigTypeTag() != .Array) return null;
17227 var ptr_inst = Air.refToIndex(ptr) orelse return null;
17228 const air_datas = sema.air_instructions.items(.data);
17229 const air_tags = sema.air_instructions.items(.tag);
17230 const prev_ptr = while (air_tags[ptr_inst] == .bitcast) {
17231 const prev_ptr = air_datas[ptr_inst].ty_op.operand;
17232 const prev_ptr_ty = sema.typeOf(prev_ptr);
17233 const prev_ptr_child_ty = switch (prev_ptr_ty.tag()) {
17234 .single_mut_pointer => prev_ptr_ty.castTag(.single_mut_pointer).?.data,
17235 .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type,
17236 else => return null,
17237 };
17238 if (prev_ptr_child_ty.zigTypeTag() == .Vector) break prev_ptr;
17239 ptr_inst = Air.refToIndex(prev_ptr) orelse return null;
17240 } else return null;
17241
17242 // We have a pointer-to-array and a pointer-to-vector. If the elements and
17243 // lengths match, return the result.
17244 const vector_ty = sema.typeOf(prev_ptr).childType();
17245 if (array_ty.childType().eql(vector_ty.childType()) and
17246 array_ty.arrayLen() == vector_ty.vectorLen())
17247 {
17248 return prev_ptr;
17249 } else {
17250 return null;
17251 }
17252}
17253
17198/// Call when you have Value objects rather than Air instructions, and you want to17254/// Call when you have Value objects rather than Air instructions, and you want to
17199/// assert the store must be done at comptime.17255/// assert the store must be done at comptime.
17200fn storePtrVal(17256fn storePtrVal(
src/codegen/llvm.zig+4-2
...@@ -3709,10 +3709,11 @@ pub const FuncGen = struct {...@@ -3709,10 +3709,11 @@ pub const FuncGen = struct {
37093709
3710 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3710 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3711 const operand = try self.resolveInst(ty_op.operand);3711 const operand = try self.resolveInst(ty_op.operand);
3712 const operand_ty = self.air.typeOf(ty_op.operand);
3712 const dest_ty = self.air.typeOfIndex(inst);3713 const dest_ty = self.air.typeOfIndex(inst);
3713 const dest_llvm_ty = try self.dg.llvmType(dest_ty);3714 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
37143715
3715 if (dest_ty.isSignedInt()) {3716 if (operand_ty.isSignedInt()) {
3716 return self.builder.buildSIToFP(operand, dest_llvm_ty, "");3717 return self.builder.buildSIToFP(operand, dest_llvm_ty, "");
3717 } else {3718 } else {
3718 return self.builder.buildUIToFP(operand, dest_llvm_ty, "");3719 return self.builder.buildUIToFP(operand, dest_llvm_ty, "");
...@@ -3984,13 +3985,14 @@ pub const FuncGen = struct {...@@ -3984,13 +3985,14 @@ pub const FuncGen = struct {
3984 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3985 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3985 const operand = try self.resolveInst(pl_op.operand);3986 const operand = try self.resolveInst(pl_op.operand);
3986 const name = self.air.nullTerminatedString(pl_op.payload);3987 const name = self.air.nullTerminatedString(pl_op.payload);
3988 const ptr_ty = self.air.typeOf(pl_op.operand);
39873989
3988 const di_local_var = dib.createAutoVariable(3990 const di_local_var = dib.createAutoVariable(
3989 self.di_scope.?,3991 self.di_scope.?,
3990 name.ptr,3992 name.ptr,
3991 self.di_file.?,3993 self.di_file.?,
3992 self.prev_dbg_line,3994 self.prev_dbg_line,
3993 try self.dg.lowerDebugType(self.air.typeOf(pl_op.operand)),3995 try self.dg.lowerDebugType(ptr_ty.childType()),
3994 true, // always preserve3996 true, // always preserve
3995 0, // flags3997 0, // flags
3996 );3998 );
src/type.zig+4-5
...@@ -2573,15 +2573,14 @@ pub const Type = extern union {...@@ -2573,15 +2573,14 @@ pub const Type = extern union {
2573 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,2573 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,
2574 .array, .vector => {2574 .array, .vector => {
2575 const payload = self.cast(Payload.Array).?.data;2575 const payload = self.cast(Payload.Array).?.data;
2576 const elem_size = @maximum(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));2576 const elem_size = payload.elem_type.abiSize(target);
2577 assert(elem_size >= payload.elem_type.abiAlignment(target));
2577 return payload.len * elem_size;2578 return payload.len * elem_size;
2578 },2579 },
2579 .array_sentinel => {2580 .array_sentinel => {
2580 const payload = self.castTag(.array_sentinel).?.data;2581 const payload = self.castTag(.array_sentinel).?.data;
2581 const elem_size = std.math.max(2582 const elem_size = payload.elem_type.abiSize(target);
2582 payload.elem_type.abiAlignment(target),2583 assert(elem_size >= payload.elem_type.abiAlignment(target));
2583 payload.elem_type.abiSize(target),
2584 );
2585 return (payload.len + 1) * elem_size;2584 return (payload.len + 1) * elem_size;
2586 },2585 },
2587 .i16, .u16 => return 2,2586 .i16, .u16 => return 2,
src/value.zig+2-17
...@@ -3931,15 +3931,12 @@ pub const Value = extern union {...@@ -3931,15 +3931,12 @@ pub const Value = extern union {
3931 },3931 },
3932 80 => {3932 80 => {
3933 if (true) {3933 if (true) {
3934 @panic("TODO implement compiler_rt fabs for f80");3934 @panic("TODO implement compiler_rt fabs for f80 (__fabsx)");
3935 }3935 }
3936 const f = val.toFloat(f80);3936 const f = val.toFloat(f80);
3937 return Value.Tag.float_80.create(arena, @fabs(f));3937 return Value.Tag.float_80.create(arena, @fabs(f));
3938 },3938 },
3939 128 => {3939 128 => {
3940 if (true) {
3941 @panic("TODO implement compiler_rt fabs for f128");
3942 }
3943 const f = val.toFloat(f128);3940 const f = val.toFloat(f128);
3944 return Value.Tag.float_128.create(arena, @fabs(f));3941 return Value.Tag.float_128.create(arena, @fabs(f));
3945 },3942 },
...@@ -3963,15 +3960,12 @@ pub const Value = extern union {...@@ -3963,15 +3960,12 @@ pub const Value = extern union {
3963 },3960 },
3964 80 => {3961 80 => {
3965 if (true) {3962 if (true) {
3966 @panic("TODO implement compiler_rt floor for f80");3963 @panic("TODO implement compiler_rt floor for f80 (__floorx)");
3967 }3964 }
3968 const f = val.toFloat(f80);3965 const f = val.toFloat(f80);
3969 return Value.Tag.float_80.create(arena, @floor(f));3966 return Value.Tag.float_80.create(arena, @floor(f));
3970 },3967 },
3971 128 => {3968 128 => {
3972 if (true) {
3973 @panic("TODO implement compiler_rt floor for f128");
3974 }
3975 const f = val.toFloat(f128);3969 const f = val.toFloat(f128);
3976 return Value.Tag.float_128.create(arena, @floor(f));3970 return Value.Tag.float_128.create(arena, @floor(f));
3977 },3971 },
...@@ -4001,9 +3995,6 @@ pub const Value = extern union {...@@ -4001,9 +3995,6 @@ pub const Value = extern union {
4001 return Value.Tag.float_80.create(arena, @ceil(f));3995 return Value.Tag.float_80.create(arena, @ceil(f));
4002 },3996 },
4003 128 => {3997 128 => {
4004 if (true) {
4005 @panic("TODO implement compiler_rt ceil for f128");
4006 }
4007 const f = val.toFloat(f128);3998 const f = val.toFloat(f128);
4008 return Value.Tag.float_128.create(arena, @ceil(f));3999 return Value.Tag.float_128.create(arena, @ceil(f));
4009 },4000 },
...@@ -4033,9 +4024,6 @@ pub const Value = extern union {...@@ -4033,9 +4024,6 @@ pub const Value = extern union {
4033 return Value.Tag.float_80.create(arena, @round(f));4024 return Value.Tag.float_80.create(arena, @round(f));
4034 },4025 },
4035 128 => {4026 128 => {
4036 if (true) {
4037 @panic("TODO implement compiler_rt round for f128");
4038 }
4039 const f = val.toFloat(f128);4027 const f = val.toFloat(f128);
4040 return Value.Tag.float_128.create(arena, @round(f));4028 return Value.Tag.float_128.create(arena, @round(f));
4041 },4029 },
...@@ -4065,9 +4053,6 @@ pub const Value = extern union {...@@ -4065,9 +4053,6 @@ pub const Value = extern union {
4065 return Value.Tag.float_80.create(arena, @trunc(f));4053 return Value.Tag.float_80.create(arena, @trunc(f));
4066 },4054 },
4067 128 => {4055 128 => {
4068 if (true) {
4069 @panic("TODO implement compiler_rt trunc for f128");
4070 }
4071 const f = val.toFloat(f128);4056 const f = val.toFloat(f128);
4072 return Value.Tag.float_128.create(arena, @trunc(f));4057 return Value.Tag.float_128.create(arena, @trunc(f));
4073 },4058 },
test/behavior/cast.zig+22-3
...@@ -95,8 +95,29 @@ test "comptime_int @intToFloat" {...@@ -95,8 +95,29 @@ test "comptime_int @intToFloat" {
95 }95 }
96}96}
9797
98test "@intToFloat" {
99 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103
104 const S = struct {
105 fn doTheTest() !void {
106 try testIntToFloat(-2);
107 }
108
109 fn testIntToFloat(k: i32) !void {
110 const f = @intToFloat(f32, k);
111 const i = @floatToInt(i32, f);
112 try expect(i == k);
113 }
114 };
115 try S.doTheTest();
116 comptime try S.doTheTest();
117}
118
98test "@floatToInt" {119test "@floatToInt" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO121 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
102123
...@@ -1007,8 +1028,6 @@ test "peer type resolve array pointer and unknown pointer" {...@@ -1007,8 +1028,6 @@ test "peer type resolve array pointer and unknown pointer" {
1007}1028}
10081029
1009test "comptime float casts" {1030test "comptime float casts" {
1010 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1011
1012 const a = @intToFloat(comptime_float, 1);1031 const a = @intToFloat(comptime_float, 1);
1013 try expect(a == 1);1032 try expect(a == 1);
1014 try expect(@TypeOf(a) == comptime_float);1033 try expect(@TypeOf(a) == comptime_float);
test/behavior/floatop.zig+124-21
...@@ -333,7 +333,6 @@ fn testLog() !void {...@@ -333,7 +333,6 @@ fn testLog() !void {
333}333}
334334
335test "@log with vectors" {335test "@log with vectors" {
336 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO336 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
338 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO337 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
...@@ -343,15 +342,19 @@ test "@log with vectors" {...@@ -343,15 +342,19 @@ test "@log with vectors" {
343 {342 {
344 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };343 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
345 var result = @log(v);344 var result = @log(v);
346 try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon));345 try expect(@log(@as(f32, 1.1)) == result[0]);
347 try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon));346 try expect(@log(@as(f32, 2.2)) == result[1]);
348 try expect(@log(@as(f32, 0.3)) == result[2]);347 try expect(@log(@as(f32, 0.3)) == result[2]);
349 try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon));348 try expect(@log(@as(f32, 0.4)) == result[3]);
350 }349 }
351}350}
352351
353test "@log2" {352test "@log2" {
354 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO353 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
354 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
355358
356 comptime try testLog2();359 comptime try testLog2();
357 try testLog2();360 try testLog2();
...@@ -368,15 +371,19 @@ fn testLog2() !void {...@@ -368,15 +371,19 @@ fn testLog2() !void {
368 {371 {
369 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };372 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
370 var result = @log2(v);373 var result = @log2(v);
371 try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon));374 try expect(@log2(@as(f32, 1.1)) == result[0]);
372 try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon));375 try expect(@log2(@as(f32, 2.2)) == result[1]);
373 try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon));376 try expect(@log2(@as(f32, 0.3)) == result[2]);
374 try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon));377 try expect(@log2(@as(f32, 0.4)) == result[3]);
375 }378 }
376}379}
377380
378test "@log10" {381test "@log10" {
379 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
383 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
384 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
380387
381 comptime try testLog10();388 comptime try testLog10();
382 try testLog10();389 try testLog10();
...@@ -393,10 +400,10 @@ fn testLog10() !void {...@@ -393,10 +400,10 @@ fn testLog10() !void {
393 {400 {
394 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };401 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
395 var result = @log10(v);402 var result = @log10(v);
396 try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon));403 try expect(@log10(@as(f32, 1.1)) == result[0]);
397 try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon));404 try expect(@log10(@as(f32, 2.2)) == result[1]);
398 try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon));405 try expect(@log10(@as(f32, 0.3)) == result[2]);
399 try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon));406 try expect(@log10(@as(f32, 0.4)) == result[3]);
400 }407 }
401}408}
402409
...@@ -537,7 +544,71 @@ fn testTrunc() !void {...@@ -537,7 +544,71 @@ fn testTrunc() !void {
537 }544 }
538}545}
539546
540test "negation" {547test "negation f16" {
548 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
549 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
551 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
552
553 if (builtin.os.tag == .freebsd) {
554 // TODO file issue to track this failure
555 return error.SkipZigTest;
556 }
557
558 const S = struct {
559 fn doTheTest() !void {
560 var a: f16 = 1;
561 a = -a;
562 try expect(a == -1);
563 a = -a;
564 try expect(a == 1);
565 }
566 };
567
568 try S.doTheTest();
569 comptime try S.doTheTest();
570}
571
572test "negation f32" {
573 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
577
578 const S = struct {
579 fn doTheTest() !void {
580 var a: f32 = 1;
581 a = -a;
582 try expect(a == -1);
583 a = -a;
584 try expect(a == 1);
585 }
586 };
587
588 try S.doTheTest();
589 comptime try S.doTheTest();
590}
591
592test "negation f64" {
593 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
594 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
596
597 const S = struct {
598 fn doTheTest() !void {
599 var a: f64 = 1;
600 a = -a;
601 try expect(a == -1);
602 a = -a;
603 try expect(a == 1);
604 }
605 };
606
607 try S.doTheTest();
608 comptime try S.doTheTest();
609}
610
611test "negation f80" {
541 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO612 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
542613
543 if (builtin.os.tag == .freebsd) {614 if (builtin.os.tag == .freebsd) {
...@@ -547,11 +618,37 @@ test "negation" {...@@ -547,11 +618,37 @@ test "negation" {
547618
548 const S = struct {619 const S = struct {
549 fn doTheTest() !void {620 fn doTheTest() !void {
550 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {621 var a: f80 = 1;
551 var a: T = 1;622 a = -a;
552 a = -a;623 try expect(a == -1);
553 try expect(a == -1);624 a = -a;
554 }625 try expect(a == 1);
626 }
627 };
628
629 try S.doTheTest();
630 comptime try S.doTheTest();
631}
632
633test "negation f128" {
634 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
635 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
636 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
637 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
638 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
639
640 if (builtin.os.tag == .freebsd) {
641 // TODO file issue to track this failure
642 return error.SkipZigTest;
643 }
644
645 const S = struct {
646 fn doTheTest() !void {
647 var a: f128 = 1;
648 a = -a;
649 try expect(a == -1);
650 a = -a;
651 try expect(a == 1);
555 }652 }
556 };653 };
557654
...@@ -583,7 +680,13 @@ test "float literal at compile time not lossy" {...@@ -583,7 +680,13 @@ test "float literal at compile time not lossy" {
583}680}
584681
585test "f128 at compile time is lossy" {682test "f128 at compile time is lossy" {
586 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO683 if (builtin.zig_backend != .stage1) {
684 // this one is happening because we represent comptime-known f128 integers with
685 // Value.Tag.bigint and only convert to f128 representation if it stops being an
686 // integer. Is this something we want? need to have a lang spec discussion on this
687 // topic.
688 return error.SkipZigTest; // TODO
689 }
587690
588 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);691 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
589}692}
test/behavior/math.zig+126-43
...@@ -6,7 +6,6 @@ const expectEqualSlices = std.testing.expectEqualSlices;...@@ -6,7 +6,6 @@ const expectEqualSlices = std.testing.expectEqualSlices;
6const maxInt = std.math.maxInt;6const maxInt = std.math.maxInt;
7const minInt = std.math.minInt;7const minInt = std.math.minInt;
8const mem = std.mem;8const mem = std.mem;
9const has_f80_rt = builtin.cpu.arch == .x86_64;
109
11test "assignment operators" {10test "assignment operators" {
12 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1046,12 +1045,14 @@ fn testSqrt(comptime T: type, x: T) !void {...@@ -1046,12 +1045,14 @@ fn testSqrt(comptime T: type, x: T) !void {
1046}1045}
10471046
1048test "@fabs" {1047test "@fabs" {
1049 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1048 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1049 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1050 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1051 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1052 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10501053
1051 try testFabs(f128, 12.0);1054 try testFabs(f128, 12.0);
1052 comptime try testFabs(f128, 12.0);1055 comptime try testFabs(f128, 12.0);
1053 if (has_f80_rt) try testFabs(f80, 12.0);
1054 // comptime try testFabs(f80, 12.0);
1055 try testFabs(f64, 12.0);1056 try testFabs(f64, 12.0);
1056 comptime try testFabs(f64, 12.0);1057 comptime try testFabs(f64, 12.0);
1057 try testFabs(f32, 12.0);1058 try testFabs(f32, 12.0);
...@@ -1065,20 +1066,25 @@ test "@fabs" {...@@ -1065,20 +1066,25 @@ test "@fabs" {
1065 comptime try expectEqual(x, z);1066 comptime try expectEqual(x, z);
1066}1067}
10671068
1069test "@fabs f80" {
1070 if (true) {
1071 // https://github.com/ziglang/zig/issues/11030
1072 return error.SkipZigTest;
1073 }
1074
1075 try testFabs(f80, 12.0);
1076 comptime try testFabs(f80, 12.0);
1077}
1078
1068fn testFabs(comptime T: type, x: T) !void {1079fn testFabs(comptime T: type, x: T) !void {
1069 const y = -x;1080 const y = -x;
1070 const z = @fabs(y);1081 const z = @fabs(y);
1071 try expectEqual(x, z);1082 try expect(x == z);
1072}1083}
10731084
1074test "@floor" {1085test "@floor" {
1075 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1086 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
10761087
1077 // FIXME: Generates a floorl function call
1078 // testFloor(f128, 12.0);
1079 comptime try testFloor(f128, 12.0);
1080 // try testFloor(f80, 12.0);
1081 comptime try testFloor(f80, 12.0);
1082 try testFloor(f64, 12.0);1088 try testFloor(f64, 12.0);
1083 comptime try testFloor(f64, 12.0);1089 comptime try testFloor(f64, 12.0);
1084 try testFloor(f32, 12.0);1090 try testFloor(f32, 12.0);
...@@ -1089,23 +1095,39 @@ test "@floor" {...@@ -1089,23 +1095,39 @@ test "@floor" {
1089 const x = 14.0;1095 const x = 14.0;
1090 const y = x + 0.7;1096 const y = x + 0.7;
1091 const z = @floor(y);1097 const z = @floor(y);
1092 comptime try expectEqual(x, z);1098 comptime try expect(x == z);
1099}
1100
1101test "@floor f80" {
1102 if (true) {
1103 // https://github.com/ziglang/zig/issues/11030
1104 return error.SkipZigTest;
1105 }
1106 try testFloor(f80, 12.0);
1107 comptime try testFloor(f80, 12.0);
1108}
1109
1110test "@floor f128" {
1111 if (builtin.zig_backend == .stage1) {
1112 // Fails because it incorrectly lowers to a floorl function call.
1113 return error.SkipZigTest;
1114 }
1115
1116 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1117
1118 testFloor(f128, 12.0);
1119 comptime try testFloor(f128, 12.0);
1093}1120}
10941121
1095fn testFloor(comptime T: type, x: T) !void {1122fn testFloor(comptime T: type, x: T) !void {
1096 const y = x + 0.6;1123 const y = x + 0.6;
1097 const z = @floor(y);1124 const z = @floor(y);
1098 try expectEqual(x, z);1125 try expect(x == z);
1099}1126}
11001127
1101test "@ceil" {1128test "@ceil" {
1102 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1129 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
11031130
1104 // FIXME: Generates a ceill function call
1105 //testCeil(f128, 12.0);
1106 comptime try testCeil(f128, 12.0);
1107 // try testCeil(f80, 12.0);
1108 comptime try testCeil(f80, 12.0);
1109 try testCeil(f64, 12.0);1131 try testCeil(f64, 12.0);
1110 comptime try testCeil(f64, 12.0);1132 comptime try testCeil(f64, 12.0);
1111 try testCeil(f32, 12.0);1133 try testCeil(f32, 12.0);
...@@ -1116,29 +1138,40 @@ test "@ceil" {...@@ -1116,29 +1138,40 @@ test "@ceil" {
1116 const x = 14.0;1138 const x = 14.0;
1117 const y = x - 0.7;1139 const y = x - 0.7;
1118 const z = @ceil(y);1140 const z = @ceil(y);
1119 comptime try expectEqual(x, z);1141 comptime try expect(x == z);
1142}
1143
1144test "@ceil f80" {
1145 if (true) {
1146 // https://github.com/ziglang/zig/issues/11030
1147 return error.SkipZigTest;
1148 }
1149
1150 try testCeil(f80, 12.0);
1151 comptime try testCeil(f80, 12.0);
1152}
1153
1154test "@ceil f128" {
1155 if (builtin.zig_backend == .stage1) {
1156 // Fails because it incorrectly lowers to a ceill function call.
1157 return error.SkipZigTest;
1158 }
1159
1160 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1161
1162 testCeil(f128, 12.0);
1163 comptime try testCeil(f128, 12.0);
1120}1164}
11211165
1122fn testCeil(comptime T: type, x: T) !void {1166fn testCeil(comptime T: type, x: T) !void {
1123 const y = x - 0.8;1167 const y = x - 0.8;
1124 const z = @ceil(y);1168 const z = @ceil(y);
1125 try expectEqual(x, z);1169 try expect(x == z);
1126}1170}
11271171
1128test "@trunc" {1172test "@trunc" {
1129 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1173 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
11301174
1131 // FIXME: Generates a truncl function call
1132 //testTrunc(f128, 12.0);
1133 comptime try testTrunc(f128, 12.0);
1134 // try testTrunc(f80, 12.0);
1135 // comptime try testTrunc(f80, 12.0);
1136 comptime {
1137 const x: f80 = 12.0;
1138 const y = x + 0.8;
1139 const z = @trunc(y);
1140 try expectEqual(x, z);
1141 }
1142 try testTrunc(f64, 12.0);1175 try testTrunc(f64, 12.0);
1143 comptime try testTrunc(f64, 12.0);1176 comptime try testTrunc(f64, 12.0);
1144 try testTrunc(f32, 12.0);1177 try testTrunc(f32, 12.0);
...@@ -1149,31 +1182,54 @@ test "@trunc" {...@@ -1149,31 +1182,54 @@ test "@trunc" {
1149 const x = 14.0;1182 const x = 14.0;
1150 const y = x + 0.7;1183 const y = x + 0.7;
1151 const z = @trunc(y);1184 const z = @trunc(y);
1152 comptime try expectEqual(x, z);1185 comptime try expect(x == z);
1186}
1187
1188test "@trunc f80" {
1189 if (true) {
1190 // https://github.com/ziglang/zig/issues/11030
1191 return error.SkipZigTest;
1192 }
1193
1194 try testTrunc(f80, 12.0);
1195 comptime try testTrunc(f80, 12.0);
1196 comptime {
1197 const x: f80 = 12.0;
1198 const y = x + 0.8;
1199 const z = @trunc(y);
1200 try expect(x == z);
1201 }
1202}
1203
1204test "@trunc f128" {
1205 if (builtin.zig_backend == .stage1) {
1206 // Fails because it incorrectly lowers to a truncl function call.
1207 return error.SkipZigTest;
1208 }
1209
1210 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1211
1212 testTrunc(f128, 12.0);
1213 comptime try testTrunc(f128, 12.0);
1153}1214}
11541215
1155fn testTrunc(comptime T: type, x: T) !void {1216fn testTrunc(comptime T: type, x: T) !void {
1156 {1217 {
1157 const y = x + 0.8;1218 const y = x + 0.8;
1158 const z = @trunc(y);1219 const z = @trunc(y);
1159 try expectEqual(x, z);1220 try expect(x == z);
1160 }1221 }
11611222
1162 {1223 {
1163 const y = -x - 0.8;1224 const y = -x - 0.8;
1164 const z = @trunc(y);1225 const z = @trunc(y);
1165 try expectEqual(-x, z);1226 try expect(-x == z);
1166 }1227 }
1167}1228}
11681229
1169test "@round" {1230test "@round" {
1170 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1231 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
11711232
1172 // FIXME: Generates a roundl function call
1173 //testRound(f128, 12.0);
1174 comptime try testRound(f128, 12.0);
1175 // try testRound(f80, 12.0);
1176 comptime try testRound(f80, 12.0);
1177 try testRound(f64, 12.0);1233 try testRound(f64, 12.0);
1178 comptime try testRound(f64, 12.0);1234 comptime try testRound(f64, 12.0);
1179 try testRound(f32, 12.0);1235 try testRound(f32, 12.0);
...@@ -1184,13 +1240,35 @@ test "@round" {...@@ -1184,13 +1240,35 @@ test "@round" {
1184 const x = 14.0;1240 const x = 14.0;
1185 const y = x + 0.4;1241 const y = x + 0.4;
1186 const z = @round(y);1242 const z = @round(y);
1187 comptime try expectEqual(x, z);1243 comptime try expect(x == z);
1244}
1245
1246test "@round f80" {
1247 if (true) {
1248 // https://github.com/ziglang/zig/issues/11030
1249 return error.SkipZigTest;
1250 }
1251
1252 try testRound(f80, 12.0);
1253 comptime try testRound(f80, 12.0);
1254}
1255
1256test "@round f128" {
1257 if (builtin.zig_backend == .stage1) {
1258 // Fails because it incorrectly lowers to a roundl function call.
1259 return error.SkipZigTest;
1260 }
1261
1262 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1263
1264 testRound(f128, 12.0);
1265 comptime try testRound(f128, 12.0);
1188}1266}
11891267
1190fn testRound(comptime T: type, x: T) !void {1268fn testRound(comptime T: type, x: T) !void {
1191 const y = x - 0.5;1269 const y = x - 0.5;
1192 const z = @round(y);1270 const z = @round(y);
1193 try expectEqual(x, z);1271 try expect(x == z);
1194}1272}
11951273
1196test "vector integer addition" {1274test "vector integer addition" {
...@@ -1225,10 +1303,15 @@ test "NaN comparison" {...@@ -1225,10 +1303,15 @@ test "NaN comparison" {
1225 comptime try testNanEqNan(f32);1303 comptime try testNanEqNan(f32);
1226 comptime try testNanEqNan(f64);1304 comptime try testNanEqNan(f64);
1227 comptime try testNanEqNan(f128);1305 comptime try testNanEqNan(f128);
1306}
12281307
1229 // TODO https://github.com/ziglang/zig/issues/110301308test "NaN comparison f80" {
1230 // try testNanEqNan(f80);1309 if (true) {
1231 // comptime try testNanEqNan(f80);1310 // https://github.com/ziglang/zig/issues/11030
1311 return error.SkipZigTest;
1312 }
1313 try testNanEqNan(f80);
1314 comptime try testNanEqNan(f80);
1232}1315}
12331316
1234fn testNanEqNan(comptime F: type) !void {1317fn testNanEqNan(comptime F: type) !void {
test/cases.zig+2-1
...@@ -16,5 +16,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -16,5 +16,6 @@ pub fn addCases(ctx: *TestContext) !void {
16 try @import("stage2/riscv64.zig").addCases(ctx);16 try @import("stage2/riscv64.zig").addCases(ctx);
17 try @import("stage2/plan9.zig").addCases(ctx);17 try @import("stage2/plan9.zig").addCases(ctx);
18 try @import("stage2/x86_64.zig").addCases(ctx);18 try @import("stage2/x86_64.zig").addCases(ctx);
19 try @import("stage2/nvptx.zig").addCases(ctx);19 // https://github.com/ziglang/zig/issues/10968
20 //try @import("stage2/nvptx.zig").addCases(ctx);
20}21}