authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-24 23:05:25-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:22:55-04:00
log6021edd7cee104f69c9ceb1af27e46637cab79e3
tree2eeb2f36c219ca24b44b6d24e5d68879a0228e47
parent54326cc55485fa71ce729cd553cb9af9ea816faa

cbe: add support for all float literals types


9 files changed, 76 insertions(+), 81 deletions(-)

lib/include/zig.h+2-2
......@@ -340,7 +340,7 @@ zig_int_operators(64)
340340
341341#define zig_int_helpers(w) \
342342 static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
343 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? zig_as_i##w(-1) : zig_as_i##w(0); \
343 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \
344344 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
345345 } \
346346\
......@@ -1166,7 +1166,7 @@ static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
11661166#define zig_mod_u128 zig_rem_u128
11671167
11681168static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
1169 zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? zig_as_i128(-1, UINT64_MAX) : zig_as_i128(0, 0);
1169 zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? -zig_as_i128(0, 1) : zig_as_i128(0, 0);
11701170 return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
11711171}
11721172
src/codegen/c.zig+74-64
......@@ -415,26 +415,6 @@ pub const Function = struct {
415415 },
416416 }
417417 }
418
419 fn renderFloatFnName(f: *Function, writer: anytype, operation: []const u8, float_ty: Type) !void {
420 const target = f.object.dg.module.getTarget();
421 const float_bits = float_ty.floatBits(target);
422 const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
423 try writer.writeAll("__");
424 if (is_longdouble or float_bits != 80) {
425 try writer.writeAll("builtin_");
426 }
427 try writer.writeAll(operation);
428 if (is_longdouble) {
429 try writer.writeByte('l');
430 } else switch (float_bits) {
431 16, 32 => try writer.writeByte('f'),
432 64 => {},
433 80 => try writer.writeByte('x'),
434 128 => try writer.writeByte('q'),
435 else => unreachable,
436 }
437 }
438418};
439419
440420/// This data is available when outputting .c code for a `Module`.
......@@ -674,14 +654,18 @@ pub const DeclGen = struct {
674654 // bool b = 0xaa; evals to true, but memcpy(&b, 0xaa, 1); evals to false.
675655 .Bool => return dg.renderValue(writer, ty, Value.@"false", location),
676656 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
677 .Float => switch (ty.tag()) {
678 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{
679 try dg.fmtIntLiteral(Type.u32, val),
680 }),
681 .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{
682 try dg.fmtIntLiteral(Type.u64, val),
683 }),
684 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
657 .Float => {
658 try writer.writeByte('(');
659 try dg.renderTypecast(writer, ty);
660 try writer.writeByte(')');
661 switch (ty.floatBits(target)) {
662 16 => return writer.print("{x}f", .{@bitCast(f16, undefPattern(u16))}),
663 32 => return writer.print("{x}f", .{@bitCast(f32, undefPattern(u32))}),
664 64 => return writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}),
665 80 => return writer.print("{x}l", .{@bitCast(f80, undefPattern(u80))}),
666 128 => return writer.print("{x}l", .{@bitCast(f128, undefPattern(u128))}),
667 else => unreachable,
668 }
685669 },
686670 .Pointer => switch (ty.ptrSize()) {
687671 .Slice => {
......@@ -833,37 +817,41 @@ pub const DeclGen = struct {
833817 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}),
834818 },
835819 .Float => {
836 if (ty.floatBits(target) <= 64) {
837 if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {
838 // just generate a bit cast (exactly like we do in airBitcast)
839 switch (ty.tag()) {
840 .f32 => {
841 var bitcast_pl = Value.Payload.U64{
842 .base = .{ .tag = .int_u64 },
843 .data = @bitCast(u32, val.toFloat(f32)),
844 };
845 const bitcast_val = Value.initPayload(&bitcast_pl.base);
846 return writer.print("zig_bitcast_f32_u32({x})", .{
847 try dg.fmtIntLiteral(Type.u32, bitcast_val),
848 });
849 },
850 .f64 => {
851 var bitcast_pl = Value.Payload.U64{
852 .base = .{ .tag = .int_u64 },
853 .data = @bitCast(u64, val.toFloat(f64)),
854 };
855 const bitcast_val = Value.initPayload(&bitcast_pl.base);
856 return writer.print("zig_bitcast_f64_u64({x})", .{
857 try dg.fmtIntLiteral(Type.u64, bitcast_val),
858 });
859 },
860 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
861 }
862 } else {
863 return writer.print("{x}", .{val.toFloat(f64)});
864 }
820 try writer.writeByte('(');
821 try dg.renderTypecast(writer, ty);
822 try writer.writeByte(')');
823 const f128_val = val.toFloat(f128);
824 if (!std.math.isFinite(f128_val)) {
825 if (std.math.signbit(f128_val)) try writer.writeByte('-');
826 const fn_name = if (std.math.isSignalNan(f128_val))
827 "nans"
828 else if (std.math.isNan(f128_val))
829 "nan"
830 else if (std.math.isInf(f128_val))
831 "inf"
832 else
833 unreachable;
834 try dg.renderFloatFnName(writer, fn_name, ty);
835 try writer.writeByte('(');
836 if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) {
837 // We only actually need to pass the significant, but it will get
838 // properly masked anyway, so just pass the whole value.
839 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}),
840 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}),
841 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}),
842 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}),
843 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
844 else => unreachable,
845 };
846 return writer.writeByte(')');
847 } else switch (ty.floatBits(target)) {
848 16 => return writer.print("{x}f", .{val.toFloat(f16)}),
849 32 => return writer.print("{x}f", .{val.toFloat(f32)}),
850 64 => return writer.print("{x}", .{val.toFloat(f64)}),
851 80 => return writer.print("{x}l", .{val.toFloat(f80)}),
852 128 => return writer.print("{x}l", .{f128_val}),
853 else => unreachable,
865854 }
866 return dg.fail("TODO: C backend: implement lowering large float values", .{});
867855 },
868856 .Pointer => switch (val.tag()) {
869857 .null_value, .zero => {
......@@ -2053,6 +2041,26 @@ pub const DeclGen = struct {
20532041 }
20542042 }
20552043
2044 fn renderFloatFnName(dg: *DeclGen, writer: anytype, operation: []const u8, float_ty: Type) !void {
2045 const target = dg.module.getTarget();
2046 const float_bits = float_ty.floatBits(target);
2047 const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
2048 try writer.writeAll("__");
2049 if (is_longdouble or float_bits != 80) {
2050 try writer.writeAll("builtin_");
2051 }
2052 try writer.writeAll(operation);
2053 if (is_longdouble) {
2054 try writer.writeByte('l');
2055 } else switch (float_bits) {
2056 16, 32 => try writer.writeByte('f'),
2057 64 => {},
2058 80 => try writer.writeByte('x'),
2059 128 => try writer.writeByte('q'),
2060 else => unreachable,
2061 }
2062 }
2063
20562064 fn fmtIntLiteral(
20572065 dg: *DeclGen,
20582066 ty: Type,
......@@ -5169,7 +5177,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
51695177 const operand = try f.resolveInst(un_op);
51705178 const local = try f.allocLocal(inst_ty, .Const);
51715179 try writer.writeAll(" = ");
5172 try f.renderFloatFnName(writer, operation, inst_ty);
5180 try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
51735181 try writer.writeByte('(');
51745182 try f.writeCValue(writer, operand, .FunctionArgument);
51755183 try writer.writeAll(");\n");
......@@ -5185,7 +5193,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
51855193 const rhs = try f.resolveInst(bin_op.rhs);
51865194 const local = try f.allocLocal(inst_ty, .Const);
51875195 try writer.writeAll(" = ");
5188 try f.renderFloatFnName(writer, operation, inst_ty);
5196 try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
51895197 try writer.writeByte('(');
51905198 try f.writeCValue(writer, lhs, .FunctionArgument);
51915199 try writer.writeAll(", ");
......@@ -5205,7 +5213,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
52055213 const writer = f.object.writer();
52065214 const local = try f.allocLocal(inst_ty, .Const);
52075215 try writer.writeAll(" = ");
5208 try f.renderFloatFnName(writer, "fma", inst_ty);
5216 try f.object.dg.renderFloatFnName(writer, "fma", inst_ty);
52095217 try writer.writeByte('(');
52105218 try f.writeCValue(writer, mulend1, .FunctionArgument);
52115219 try writer.writeAll(", ");
......@@ -5342,6 +5350,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) {
53425350 return .{ .data = str };
53435351}
53445352
5353fn undefPattern(comptime T: type) T {
5354 return (1 << (@bitSizeOf(T) | 1)) / 3;
5355}
5356
53455357const FormatIntLiteralContext = struct {
53465358 ty: Type,
53475359 val: Value,
......@@ -5379,9 +5391,7 @@ fn formatIntLiteral(
53795391 var int_buf: Value.BigIntSpace = undefined;
53805392 const int = if (data.val.isUndefDeep()) blk: {
53815393 undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits));
5382
5383 const undef_pattern: Limb = (1 << (@bitSizeOf(Limb) | 1)) / 3;
5384 std.mem.set(Limb, undef_limbs, undef_pattern);
5394 std.mem.set(Limb, undef_limbs, undefPattern(Limb));
53855395
53865396 var undef_int = BigInt.Mutable{
53875397 .limbs = undef_limbs,
test/behavior/bugs/12891.zig-1
......@@ -8,7 +8,6 @@ test "issue12891" {
88}
99test "nan" {
1010 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211
1312 const f = comptime std.math.nan(f64);
1413 var i: usize = 0;
test/behavior/cast.zig-2
......@@ -1283,7 +1283,6 @@ fn boolToStr(b: bool) []const u8 {
12831283
12841284test "cast f16 to wider types" {
12851285 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1286 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12871286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12881287 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12891288 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1302,7 +1301,6 @@ test "cast f16 to wider types" {
13021301
13031302test "cast f128 to narrower types" {
13041303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1305 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13061304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13071305 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13081306 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig-6
......@@ -147,7 +147,6 @@ fn testSqrt() !void {
147147
148148test "more @sqrt f16 tests" {
149149 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
150 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
151150 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
152151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
153152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -608,7 +607,6 @@ test "negation f80" {
608607 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
609608 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
610609 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
611 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
612610 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
613611
614612 const S = struct {
......@@ -629,7 +627,6 @@ test "negation f128" {
629627 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
630628 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
631629 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
632 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
633630 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
634631
635632 const S = struct {
......@@ -709,7 +706,6 @@ test "nan negation f16" {
709706 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
710707 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
711708 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
712 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
713709
714710 const nan_comptime = comptime math.nan(f16);
715711 const neg_nan_comptime = -nan_comptime;
......@@ -729,7 +725,6 @@ test "nan negation f32" {
729725 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
730726 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
731727 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
733728
734729 const nan_comptime = comptime math.nan(f32);
735730 const neg_nan_comptime = -nan_comptime;
......@@ -749,7 +744,6 @@ test "nan negation f64" {
749744 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
750745 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
751746 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
752 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
753747
754748 const nan_comptime = comptime math.nan(f64);
755749 const neg_nan_comptime = -nan_comptime;
test/behavior/math.zig-2
......@@ -1316,7 +1316,6 @@ test "@fabs f80" {
13161316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13171317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13181318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1319 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13201319
13211320 try testFabs(f80, 12.0);
13221321 comptime try testFabs(f80, 12.0);
......@@ -1625,7 +1624,6 @@ test "compare undefined literal with comptime_int" {
16251624}
16261625
16271626test "signed zeros are represented properly" {
1628 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16291627 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16301628 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16311629 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/muladd.zig-1
......@@ -44,7 +44,6 @@ fn testMulAdd16() !void {
4444
4545test "@mulAdd f80" {
4646 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
47 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4847 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4948 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5049 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/pointers.zig-1
......@@ -335,7 +335,6 @@ test "pointer sentinel with optional element" {
335335
336336test "pointer sentinel with +inf" {
337337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
338 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
339338 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
340339 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
341340 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/tuple.zig-2
......@@ -205,7 +205,6 @@ test "initializing anon struct with explicit type" {
205205}
206206
207207test "fieldParentPtr of tuple" {
208 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
209208 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
210209 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
211210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -216,7 +215,6 @@ test "fieldParentPtr of tuple" {
216215}
217216
218217test "fieldParentPtr of anon struct" {
219 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
220218 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
221219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
222220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;