Commit 6021edd7ce
Changed files (9)
lib
include
src
codegen
test
lib/include/zig.h
@@ -340,7 +340,7 @@ zig_int_operators(64)
#define zig_int_helpers(w) \
static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
- zig_i##w sign_mask = lhs < zig_as_i##w(0) ? zig_as_i##w(-1) : zig_as_i##w(0); \
+ zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \
return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
} \
\
@@ -1166,7 +1166,7 @@ static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
#define zig_mod_u128 zig_rem_u128
static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
- 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);
+ 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);
return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
}
src/codegen/c.zig
@@ -415,26 +415,6 @@ pub const Function = struct {
},
}
}
-
- fn renderFloatFnName(f: *Function, writer: anytype, operation: []const u8, float_ty: Type) !void {
- const target = f.object.dg.module.getTarget();
- const float_bits = float_ty.floatBits(target);
- const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
- try writer.writeAll("__");
- if (is_longdouble or float_bits != 80) {
- try writer.writeAll("builtin_");
- }
- try writer.writeAll(operation);
- if (is_longdouble) {
- try writer.writeByte('l');
- } else switch (float_bits) {
- 16, 32 => try writer.writeByte('f'),
- 64 => {},
- 80 => try writer.writeByte('x'),
- 128 => try writer.writeByte('q'),
- else => unreachable,
- }
- }
};
/// This data is available when outputting .c code for a `Module`.
@@ -674,14 +654,18 @@ pub const DeclGen = struct {
// bool b = 0xaa; evals to true, but memcpy(&b, 0xaa, 1); evals to false.
.Bool => return dg.renderValue(writer, ty, Value.@"false", location),
.Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
- .Float => switch (ty.tag()) {
- .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{
- try dg.fmtIntLiteral(Type.u32, val),
- }),
- .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{
- try dg.fmtIntLiteral(Type.u64, val),
- }),
- else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
+ .Float => {
+ try writer.writeByte('(');
+ try dg.renderTypecast(writer, ty);
+ try writer.writeByte(')');
+ switch (ty.floatBits(target)) {
+ 16 => return writer.print("{x}f", .{@bitCast(f16, undefPattern(u16))}),
+ 32 => return writer.print("{x}f", .{@bitCast(f32, undefPattern(u32))}),
+ 64 => return writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}),
+ 80 => return writer.print("{x}l", .{@bitCast(f80, undefPattern(u80))}),
+ 128 => return writer.print("{x}l", .{@bitCast(f128, undefPattern(u128))}),
+ else => unreachable,
+ }
},
.Pointer => switch (ty.ptrSize()) {
.Slice => {
@@ -833,37 +817,41 @@ pub const DeclGen = struct {
else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}),
},
.Float => {
- if (ty.floatBits(target) <= 64) {
- if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {
- // just generate a bit cast (exactly like we do in airBitcast)
- switch (ty.tag()) {
- .f32 => {
- var bitcast_pl = Value.Payload.U64{
- .base = .{ .tag = .int_u64 },
- .data = @bitCast(u32, val.toFloat(f32)),
- };
- const bitcast_val = Value.initPayload(&bitcast_pl.base);
- return writer.print("zig_bitcast_f32_u32({x})", .{
- try dg.fmtIntLiteral(Type.u32, bitcast_val),
- });
- },
- .f64 => {
- var bitcast_pl = Value.Payload.U64{
- .base = .{ .tag = .int_u64 },
- .data = @bitCast(u64, val.toFloat(f64)),
- };
- const bitcast_val = Value.initPayload(&bitcast_pl.base);
- return writer.print("zig_bitcast_f64_u64({x})", .{
- try dg.fmtIntLiteral(Type.u64, bitcast_val),
- });
- },
- else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
- }
- } else {
- return writer.print("{x}", .{val.toFloat(f64)});
- }
+ try writer.writeByte('(');
+ try dg.renderTypecast(writer, ty);
+ try writer.writeByte(')');
+ const f128_val = val.toFloat(f128);
+ if (!std.math.isFinite(f128_val)) {
+ if (std.math.signbit(f128_val)) try writer.writeByte('-');
+ const fn_name = if (std.math.isSignalNan(f128_val))
+ "nans"
+ else if (std.math.isNan(f128_val))
+ "nan"
+ else if (std.math.isInf(f128_val))
+ "inf"
+ else
+ unreachable;
+ try dg.renderFloatFnName(writer, fn_name, ty);
+ try writer.writeByte('(');
+ if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) {
+ // We only actually need to pass the significant, but it will get
+ // properly masked anyway, so just pass the whole value.
+ 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}),
+ 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}),
+ 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}),
+ 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}),
+ 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
+ else => unreachable,
+ };
+ return writer.writeByte(')');
+ } else switch (ty.floatBits(target)) {
+ 16 => return writer.print("{x}f", .{val.toFloat(f16)}),
+ 32 => return writer.print("{x}f", .{val.toFloat(f32)}),
+ 64 => return writer.print("{x}", .{val.toFloat(f64)}),
+ 80 => return writer.print("{x}l", .{val.toFloat(f80)}),
+ 128 => return writer.print("{x}l", .{f128_val}),
+ else => unreachable,
}
- return dg.fail("TODO: C backend: implement lowering large float values", .{});
},
.Pointer => switch (val.tag()) {
.null_value, .zero => {
@@ -2053,6 +2041,26 @@ pub const DeclGen = struct {
}
}
+ fn renderFloatFnName(dg: *DeclGen, writer: anytype, operation: []const u8, float_ty: Type) !void {
+ const target = dg.module.getTarget();
+ const float_bits = float_ty.floatBits(target);
+ const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
+ try writer.writeAll("__");
+ if (is_longdouble or float_bits != 80) {
+ try writer.writeAll("builtin_");
+ }
+ try writer.writeAll(operation);
+ if (is_longdouble) {
+ try writer.writeByte('l');
+ } else switch (float_bits) {
+ 16, 32 => try writer.writeByte('f'),
+ 64 => {},
+ 80 => try writer.writeByte('x'),
+ 128 => try writer.writeByte('q'),
+ else => unreachable,
+ }
+ }
+
fn fmtIntLiteral(
dg: *DeclGen,
ty: Type,
@@ -5169,7 +5177,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
const operand = try f.resolveInst(un_op);
const local = try f.allocLocal(inst_ty, .Const);
try writer.writeAll(" = ");
- try f.renderFloatFnName(writer, operation, inst_ty);
+ try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
try writer.writeByte('(');
try f.writeCValue(writer, operand, .FunctionArgument);
try writer.writeAll(");\n");
@@ -5185,7 +5193,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
const rhs = try f.resolveInst(bin_op.rhs);
const local = try f.allocLocal(inst_ty, .Const);
try writer.writeAll(" = ");
- try f.renderFloatFnName(writer, operation, inst_ty);
+ try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
try writer.writeByte('(');
try f.writeCValue(writer, lhs, .FunctionArgument);
try writer.writeAll(", ");
@@ -5205,7 +5213,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst_ty, .Const);
try writer.writeAll(" = ");
- try f.renderFloatFnName(writer, "fma", inst_ty);
+ try f.object.dg.renderFloatFnName(writer, "fma", inst_ty);
try writer.writeByte('(');
try f.writeCValue(writer, mulend1, .FunctionArgument);
try writer.writeAll(", ");
@@ -5342,6 +5350,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) {
return .{ .data = str };
}
+fn undefPattern(comptime T: type) T {
+ return (1 << (@bitSizeOf(T) | 1)) / 3;
+}
+
const FormatIntLiteralContext = struct {
ty: Type,
val: Value,
@@ -5379,9 +5391,7 @@ fn formatIntLiteral(
var int_buf: Value.BigIntSpace = undefined;
const int = if (data.val.isUndefDeep()) blk: {
undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits));
-
- const undef_pattern: Limb = (1 << (@bitSizeOf(Limb) | 1)) / 3;
- std.mem.set(Limb, undef_limbs, undef_pattern);
+ std.mem.set(Limb, undef_limbs, undefPattern(Limb));
var undef_int = BigInt.Mutable{
.limbs = undef_limbs,
test/behavior/bugs/12891.zig
@@ -8,7 +8,6 @@ test "issue12891" {
}
test "nan" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const f = comptime std.math.nan(f64);
var i: usize = 0;
test/behavior/cast.zig
@@ -1283,7 +1283,6 @@ fn boolToStr(b: bool) []const u8 {
test "cast f16 to wider types" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
@@ -1302,7 +1301,6 @@ test "cast f16 to wider types" {
test "cast f128 to narrower types" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig
@@ -147,7 +147,6 @@ fn testSqrt() !void {
test "more @sqrt f16 tests" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@@ -608,7 +607,6 @@ test "negation f80" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
const S = struct {
@@ -629,7 +627,6 @@ test "negation f128" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
const S = struct {
@@ -709,7 +706,6 @@ test "nan negation f16" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const nan_comptime = comptime math.nan(f16);
const neg_nan_comptime = -nan_comptime;
@@ -729,7 +725,6 @@ test "nan negation f32" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const nan_comptime = comptime math.nan(f32);
const neg_nan_comptime = -nan_comptime;
@@ -749,7 +744,6 @@ test "nan negation f64" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const nan_comptime = comptime math.nan(f64);
const neg_nan_comptime = -nan_comptime;
test/behavior/math.zig
@@ -1316,7 +1316,6 @@ test "@fabs f80" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
try testFabs(f80, 12.0);
comptime try testFabs(f80, 12.0);
@@ -1625,7 +1624,6 @@ test "compare undefined literal with comptime_int" {
}
test "signed zeros are represented properly" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/muladd.zig
@@ -44,7 +44,6 @@ fn testMulAdd16() !void {
test "@mulAdd f80" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/pointers.zig
@@ -335,7 +335,6 @@ test "pointer sentinel with optional element" {
test "pointer sentinel with +inf" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/tuple.zig
@@ -205,7 +205,6 @@ test "initializing anon struct with explicit type" {
}
test "fieldParentPtr of tuple" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
@@ -216,7 +215,6 @@ test "fieldParentPtr of tuple" {
}
test "fieldParentPtr of anon struct" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;