authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-18 22:43:34-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log6921b0a850771fa7729930a9ec64b27b4e57e79b
treef912dd86a68fd4866b423b698e30edec25247c33
parentb48417aed25db27aa3b200c2f118b88b8f91c48c

cbe: implement some float ops


3 files changed, 68 insertions(+), 17 deletions(-)

src/codegen/c.zig+68-13
......@@ -336,6 +336,26 @@ pub const Function = struct {
336336 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
337337 return f.object.dg.fmtIntLiteral(ty, val);
338338 }
339
340 fn renderFloatFnName(f: *Function, fn_name: []const u8, float_ty: Type) !void {
341 const target = f.object.dg.module.getTarget();
342 const float_bits = float_ty.floatBits(target);
343 const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
344 const writer = f.object.writer();
345 if (!is_longdouble and float_bits == 80) {
346 try writer.writeAll("__");
347 }
348 try writer.writeAll(fn_name);
349 if (is_longdouble) {
350 try writer.writeByte('l');
351 } else switch (float_bits) {
352 16, 32 => try writer.writeByte('f'),
353 64 => {},
354 80 => try writer.writeByte('x'),
355 128 => try writer.writeByte('q'),
356 else => unreachable,
357 }
358 }
339359};
340360
341361/// This data is available when outputting .c code for a `Module`.
......@@ -2076,8 +2096,17 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
20762096 .sub => try airBinOp (f, inst, " - "),
20772097 .mul => try airBinOp (f, inst, " * "),
20782098 .div_float, .div_exact => try airBinOp( f, inst, " / "),
2079 .rem => try airBinOp( f, inst, " % "),
20802099
2100 .rem => blk: {
2101 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2102 const lhs_ty = f.air.typeOf(bin_op.lhs);
2103 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2104 // so we only check one.
2105 break :blk if (lhs_ty.isInt())
2106 try airBinOp(f, inst, " % ")
2107 else
2108 try airBinFloatOp(f, inst, "fmod"); // yes, @rem() => fmod()
2109 },
20812110 .div_trunc => blk: {
20822111 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
20832112 const lhs_ty = f.air.typeOf(bin_op.lhs);
......@@ -2115,8 +2144,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21152144 .floor,
21162145 .ceil,
21172146 .round,
2118 .trunc_float,
2119 => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}),
2147 => |tag| try airUnFloatOp(f, inst, @tagName(tag)),
2148 .trunc_float => try airUnFloatOp(f, inst, "trunc"),
21202149
21212150 .mul_add => try airMulAdd(f, inst),
21222151
......@@ -4573,12 +4602,45 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
45734602 const inst_ty = f.air.typeOfIndex(inst);
45744603 const operand = try f.resolveInst(un_op);
45754604 const local = try f.allocLocal(inst_ty, .Const);
4576 try writer.writeByte('-');
4605 try writer.writeAll(" = -");
45774606 try f.writeCValue(writer, operand);
45784607 try writer.writeAll(";\n");
45794608 return local;
45804609}
45814610
4611fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
4612 if (f.liveness.isUnused(inst)) return CValue.none;
4613 const un_op = f.air.instructions.items(.data)[inst].un_op;
4614 const writer = f.object.writer();
4615 const inst_ty = f.air.typeOfIndex(inst);
4616 const operand = try f.resolveInst(un_op);
4617 const local = try f.allocLocal(inst_ty, .Const);
4618 try writer.writeAll(" = ");
4619 try f.renderFloatFnName(fn_name, inst_ty);
4620 try writer.writeByte('(');
4621 try f.writeCValue(writer, operand);
4622 try writer.writeAll(");\n");
4623 return local;
4624}
4625
4626fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
4627 if (f.liveness.isUnused(inst)) return CValue.none;
4628 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4629 const writer = f.object.writer();
4630 const inst_ty = f.air.typeOfIndex(inst);
4631 const lhs = try f.resolveInst(bin_op.lhs);
4632 const rhs = try f.resolveInst(bin_op.rhs);
4633 const local = try f.allocLocal(inst_ty, .Const);
4634 try writer.writeAll(" = ");
4635 try f.renderFloatFnName(fn_name, inst_ty);
4636 try writer.writeByte('(');
4637 try f.writeCValue(writer, lhs);
4638 try writer.writeAll(", ");
4639 try f.writeCValue(writer, rhs);
4640 try writer.writeAll(");\n");
4641 return local;
4642}
4643
45824644fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
45834645 if (f.liveness.isUnused(inst)) return CValue.none;
45844646 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
......@@ -4588,17 +4650,10 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
45884650 const mulend2 = try f.resolveInst(extra.rhs);
45894651 const addend = try f.resolveInst(pl_op.operand);
45904652 const writer = f.object.writer();
4591 const target = f.object.dg.module.getTarget();
4592 const fn_name = switch (inst_ty.floatBits(target)) {
4593 16, 32 => "fmaf",
4594 64 => "fma",
4595 80 => if (CType.longdouble.sizeInBits(target) == 80) "fmal" else "__fmax",
4596 128 => if (CType.longdouble.sizeInBits(target) == 128) "fmal" else "fmaq",
4597 else => unreachable,
4598 };
45994653 const local = try f.allocLocal(inst_ty, .Const);
46004654 try writer.writeAll(" = ");
4601 try writer.print("{s}(", .{fn_name});
4655 try f.renderFloatFnName("fma", inst_ty);
4656 try writer.writeByte('(');
46024657 try f.writeCValue(writer, mulend1);
46034658 try writer.writeAll(", ");
46044659 try f.writeCValue(writer, mulend2);
test/behavior/floatop.zig-2
......@@ -571,7 +571,6 @@ test "negation f32" {
571571 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
572572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
573573 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
575574 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
576575
577576 const S = struct {
......@@ -593,7 +592,6 @@ test "negation f64" {
593592 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
594593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
595594 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
597595
598596 const S = struct {
599597 fn doTheTest() !void {
test/behavior/math.zig-2
......@@ -376,7 +376,6 @@ fn testBinaryNot(x: u16) !void {
376376}
377377
378378test "division" {
379 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
380379 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
381380 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
382381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1706,7 +1705,6 @@ test "absFloat" {
17061705 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17071706 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17081707 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1709 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
17101708
17111709 try testAbsFloat();
17121710 comptime try testAbsFloat();