aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2022-10-24 23:52:13 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2022-10-25 05:22:55 -0400
commit94425fe46edb326c38ccf87872b2167bc8f24643 (patch)
treef1314273ee8bc88729636ef63e7039a31db3f338 /src
parent6021edd7cee104f69c9ceb1af27e46637cab79e3 (diff)
downloadzig-94425fe46edb326c38ccf87872b2167bc8f24643.tar.gz
zig-94425fe46edb326c38ccf87872b2167bc8f24643.zip
cbe: improve floating point type support
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig223
1 files changed, 109 insertions, 114 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 6db5f5df5a..74a4fb178a 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -367,54 +367,6 @@ pub const Function = struct {
fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
return f.object.dg.fmtIntLiteral(ty, val);
}
-
- fn renderTypeForBuiltinFnName(f: *Function, writer: anytype, ty: Type) !void {
- const target = f.object.dg.module.getTarget();
- const c_bits = if (ty.isAbiInt()) c_bits: {
- const int_info = ty.intInfo(target);
- try writer.writeByte(signAbbrev(int_info.signedness));
- break :c_bits toCIntBits(int_info.bits) orelse
- return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
- } else if (ty.isRuntimeFloat()) c_bits: {
- try writer.writeByte('f');
- break :c_bits ty.floatBits(target);
- } else return f.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
- ty.fmt(f.object.dg.module),
- });
- try writer.print("{d}", .{c_bits});
- }
-
- fn renderBuiltinInfo(f: *Function, writer: anytype, ty: Type, info: BuiltinInfo) !void {
- const target = f.object.dg.module.getTarget();
- switch (info) {
- .None => {},
- .Range => {
- var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
- defer arena.deinit();
-
- const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
- var stack align(@alignOf(ExpectedContents)) =
- std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
-
- const int_info = ty.intInfo(target);
- if (int_info.signedness == .signed) {
- const min_val = try ty.minInt(stack.get(), target);
- try writer.print(", {x}", .{try f.object.dg.fmtIntLiteral(ty, min_val)});
- }
-
- const max_val = try ty.maxInt(stack.get(), target);
- try writer.print(", {x}", .{try f.object.dg.fmtIntLiteral(ty, max_val)});
- },
- .Bits => {
- var bits_pl = Value.Payload.U64{
- .base = .{ .tag = .int_u64 },
- .data = ty.bitSize(target),
- };
- const bits_val = Value.initPayload(&bits_pl.base);
- try writer.print(", {}", .{try f.object.dg.fmtIntLiteral(Type.u8, bits_val)});
- },
- }
- }
};
/// This data is available when outputting .c code for a `Module`.
@@ -657,15 +609,18 @@ pub const DeclGen = struct {
.Float => {
try writer.writeByte('(');
try dg.renderTypecast(writer, ty);
- try writer.writeByte(')');
+ try writer.writeAll(")zig_suffix_");
+ try dg.renderTypeForBuiltinFnName(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))}),
+ 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(u16))}),
+ 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(u32))}),
+ 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}),
+ 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(u80))}),
+ 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(u128))}),
else => unreachable,
}
+ return writer.writeByte(')');
},
.Pointer => switch (ty.ptrSize()) {
.Slice => {
@@ -821,9 +776,21 @@ pub const DeclGen = struct {
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))
+ if (std.math.signbit(f128_val)) try writer.writeByte('-');
+ if (std.math.isFinite(f128_val)) {
+ try writer.writeAll("zig_suffix_");
+ try dg.renderTypeForBuiltinFnName(writer, ty);
+ try writer.writeByte('(');
+ switch (ty.floatBits(target)) {
+ 16 => try writer.print("{x}", .{@fabs(val.toFloat(f16))}),
+ 32 => try writer.print("{x}", .{@fabs(val.toFloat(f32))}),
+ 64 => try writer.print("{x}", .{@fabs(val.toFloat(f64))}),
+ 80 => try writer.print("{x}", .{@fabs(val.toFloat(f80))}),
+ 128 => try writer.print("{x}", .{@fabs(f128_val)}),
+ else => unreachable,
+ }
+ } else {
+ const operation = if (std.math.isSignalNan(f128_val))
"nans"
else if (std.math.isNan(f128_val))
"nan"
@@ -831,27 +798,23 @@ pub const DeclGen = struct {
"inf"
else
unreachable;
- try dg.renderFloatFnName(writer, fn_name, ty);
+ try writer.writeAll("zig_builtin_");
+ try dg.renderTypeForBuiltinFnName(writer, ty);
try writer.writeByte('(');
+ try writer.writeAll(operation);
+ try writer.writeAll(")(");
if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) {
- // We only actually need to pass the significant, but it will get
+ // We only actually need to pass the significand, 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)}),
+ 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, @fabs(val.toFloat(f16)))}),
+ 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, @fabs(val.toFloat(f32)))}),
+ 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, @fabs(val.toFloat(f64)))}),
+ 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, @fabs(val.toFloat(f80)))}),
+ 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, @fabs(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 writer.writeByte(')');
},
.Pointer => switch (val.tag()) {
.null_value, .zero => {
@@ -2041,23 +2004,51 @@ pub const DeclGen = struct {
}
}
- fn renderFloatFnName(dg: *DeclGen, writer: anytype, operation: []const u8, float_ty: Type) !void {
+ fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, 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,
+ const c_bits = if (ty.isAbiInt()) c_bits: {
+ const int_info = ty.intInfo(target);
+ try writer.writeByte(signAbbrev(int_info.signedness));
+ break :c_bits toCIntBits(int_info.bits) orelse
+ return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
+ } else if (ty.isRuntimeFloat()) c_bits: {
+ try writer.writeByte('f');
+ break :c_bits ty.floatBits(target);
+ } else return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
+ ty.fmt(dg.module),
+ });
+ try writer.print("{d}", .{c_bits});
+ }
+
+ fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
+ const target = dg.module.getTarget();
+ switch (info) {
+ .None => {},
+ .Range => {
+ var arena = std.heap.ArenaAllocator.init(dg.gpa);
+ defer arena.deinit();
+
+ const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
+ var stack align(@alignOf(ExpectedContents)) =
+ std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
+
+ const int_info = ty.intInfo(target);
+ if (int_info.signedness == .signed) {
+ const min_val = try ty.minInt(stack.get(), target);
+ try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val)});
+ }
+
+ const max_val = try ty.maxInt(stack.get(), target);
+ try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val)});
+ },
+ .Bits => {
+ var bits_pl = Value.Payload.U64{
+ .base = .{ .tag = .int_u64 },
+ .data = ty.bitSize(target),
+ };
+ const bits_val = Value.initPayload(&bits_pl.base);
+ try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val)});
+ },
}
}
@@ -2760,15 +2751,15 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
try writer.writeAll(" = (");
try f.renderTypecast(writer, inst_ty);
try writer.writeAll(")zig_wrap_");
- try f.renderTypeForBuiltinFnName(writer, field_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty);
try writer.writeAll("((");
try f.renderTypecast(writer, field_ty);
try writer.writeAll(")zig_shr_");
- try f.renderTypeForBuiltinFnName(writer, host_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
try writer.writeByte('(');
try f.writeCValueDeref(writer, operand);
try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
- try f.renderBuiltinInfo(writer, field_ty, .Bits);
+ try f.object.dg.renderBuiltinInfo(writer, field_ty, .Bits);
try writer.writeByte(')');
} else {
try writer.writeAll(" = ");
@@ -2998,13 +2989,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
try f.writeCValueDeref(writer, ptr_val);
try writer.writeAll(" = zig_or_");
- try f.renderTypeForBuiltinFnName(writer, host_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
try writer.writeAll("(zig_and_");
- try f.renderTypeForBuiltinFnName(writer, host_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
try writer.writeByte('(');
try f.writeCValueDeref(writer, ptr_val);
try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
- try f.renderTypeForBuiltinFnName(writer, host_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
try writer.writeAll("((");
try f.renderTypecast(writer, host_ty);
try writer.writeByte(')');
@@ -3040,14 +3031,14 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
try w.writeAll(".field_1 = zig_");
try w.writeAll(operation);
try w.writeAll("o_");
- try f.renderTypeForBuiltinFnName(w, scalar_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
try w.writeAll("(&");
try f.writeCValueMember(w, local, .{ .identifier = "field_0" });
try w.writeAll(", ");
try f.writeCValue(w, lhs, .FunctionArgument);
try w.writeAll(", ");
try f.writeCValue(w, rhs, .FunctionArgument);
- try f.renderBuiltinInfo(w, scalar_ty, info);
+ try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
try w.writeAll(");\n");
return local;
}
@@ -4217,17 +4208,17 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const temp_local = try f.allocLocal(field_int_ty, .Const);
try writer.writeAll(" = zig_wrap_");
- try f.renderTypeForBuiltinFnName(writer, field_int_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
try writer.writeAll("((");
try f.renderTypecast(writer, field_int_ty);
try writer.writeAll(")zig_shr_");
- try f.renderTypeForBuiltinFnName(writer, struct_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
try writer.writeByte('(');
try f.writeCValue(writer, struct_byval, .Other);
try writer.writeAll(", ");
try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
try writer.writeByte(')');
- try f.renderBuiltinInfo(writer, field_int_ty, .Bits);
+ try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .Bits);
try writer.writeAll(");\n");
if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
@@ -4567,10 +4558,10 @@ fn airUnBuiltinCall(
try writer.writeAll(" = zig_");
try writer.writeAll(operation);
try writer.writeByte('_');
- try f.renderTypeForBuiltinFnName(writer, operand_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
try writer.writeByte('(');
try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);
- try f.renderBuiltinInfo(writer, operand_ty, info);
+ try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
try writer.writeAll(");\n");
return local;
}
@@ -4592,12 +4583,12 @@ fn airBinBuiltinCall(
try writer.writeAll(" = zig_");
try writer.writeAll(operation);
try writer.writeByte('_');
- try f.renderTypeForBuiltinFnName(writer, operand_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
try writer.writeByte('(');
try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
try writer.writeAll(", ");
try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
- try f.renderBuiltinInfo(writer, operand_ty, info);
+ try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
try writer.writeAll(");\n");
return local;
}
@@ -4612,7 +4603,7 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !
const local = try f.allocLocal(inst_ty, .Const);
const writer = f.object.writer();
try writer.writeAll(" = zig_cmp_");
- try f.renderTypeForBuiltinFnName(writer, operand_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
try writer.writeByte('(');
try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
try writer.writeAll(", ");
@@ -5027,7 +5018,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
if (!empty) {
try writer.writeAll("zig_or_");
- try f.renderTypeForBuiltinFnName(writer, inst_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
try writer.writeByte('(');
}
empty = false;
@@ -5039,14 +5030,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
if (!empty) try writer.writeAll(", ");
try writer.writeAll("zig_shlw_");
- try f.renderTypeForBuiltinFnName(writer, inst_ty);
+ try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
try writer.writeAll("((");
try f.renderTypecast(writer, inst_ty);
try writer.writeByte(')');
try f.writeCValue(writer, try f.resolveInst(element), .Other);
try writer.writeAll(", ");
try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
- try f.renderBuiltinInfo(writer, inst_ty, .Bits);
+ try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits);
try writer.writeByte(')');
if (!empty) try writer.writeByte(')');
@@ -5176,9 +5167,11 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
const inst_ty = f.air.typeOfIndex(inst);
const operand = try f.resolveInst(un_op);
const local = try f.allocLocal(inst_ty, .Const);
- try writer.writeAll(" = ");
- try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
+ try writer.writeAll(" = zig_builtin_");
+ try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
try writer.writeByte('(');
+ try writer.writeAll(operation);
+ try writer.writeAll(")(");
try f.writeCValue(writer, operand, .FunctionArgument);
try writer.writeAll(");\n");
return local;
@@ -5192,9 +5185,11 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
const lhs = try f.resolveInst(bin_op.lhs);
const rhs = try f.resolveInst(bin_op.rhs);
const local = try f.allocLocal(inst_ty, .Const);
- try writer.writeAll(" = ");
- try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
+ try writer.writeAll(" = zig_builtin_");
+ try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
try writer.writeByte('(');
+ try writer.writeAll(operation);
+ try writer.writeAll(")(");
try f.writeCValue(writer, lhs, .FunctionArgument);
try writer.writeAll(", ");
try f.writeCValue(writer, rhs, .FunctionArgument);
@@ -5212,9 +5207,9 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
const addend = try f.resolveInst(pl_op.operand);
const writer = f.object.writer();
const local = try f.allocLocal(inst_ty, .Const);
- try writer.writeAll(" = ");
- try f.object.dg.renderFloatFnName(writer, "fma", inst_ty);
- try writer.writeByte('(');
+ try writer.writeAll(" = zig_builtin_");
+ try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
+ try writer.writeAll("(fma)(");
try f.writeCValue(writer, mulend1, .FunctionArgument);
try writer.writeAll(", ");
try f.writeCValue(writer, mulend2, .FunctionArgument);