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 {...@@ -336,6 +336,26 @@ pub const Function = struct {
336 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {336 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
337 return f.object.dg.fmtIntLiteral(ty, val);337 return f.object.dg.fmtIntLiteral(ty, val);
338 }338 }
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 }
339};359};
340360
341/// This data is available when outputting .c code for a `Module`.361/// 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...@@ -2076,8 +2096,17 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2076 .sub => try airBinOp (f, inst, " - "),2096 .sub => try airBinOp (f, inst, " - "),
2077 .mul => try airBinOp (f, inst, " * "),2097 .mul => try airBinOp (f, inst, " * "),
2078 .div_float, .div_exact => try airBinOp( f, inst, " / "),2098 .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 },
2081 .div_trunc => blk: {2110 .div_trunc => blk: {
2082 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2111 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2083 const lhs_ty = f.air.typeOf(bin_op.lhs);2112 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...@@ -2115,8 +2144,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2115 .floor,2144 .floor,
2116 .ceil,2145 .ceil,
2117 .round,2146 .round,
2118 .trunc_float,2147 => |tag| try airUnFloatOp(f, inst, @tagName(tag)),
2119 => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}),2148 .trunc_float => try airUnFloatOp(f, inst, "trunc"),
21202149
2121 .mul_add => try airMulAdd(f, inst),2150 .mul_add => try airMulAdd(f, inst),
21222151
...@@ -4573,12 +4602,45 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4573,12 +4602,45 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
4573 const inst_ty = f.air.typeOfIndex(inst);4602 const inst_ty = f.air.typeOfIndex(inst);
4574 const operand = try f.resolveInst(un_op);4603 const operand = try f.resolveInst(un_op);
4575 const local = try f.allocLocal(inst_ty, .Const);4604 const local = try f.allocLocal(inst_ty, .Const);
4576 try writer.writeByte('-');4605 try writer.writeAll(" = -");
4577 try f.writeCValue(writer, operand);4606 try f.writeCValue(writer, operand);
4578 try writer.writeAll(";\n");4607 try writer.writeAll(";\n");
4579 return local;4608 return local;
4580}4609}
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
4582fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {4644fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
4583 if (f.liveness.isUnused(inst)) return CValue.none;4645 if (f.liveness.isUnused(inst)) return CValue.none;
4584 const pl_op = f.air.instructions.items(.data)[inst].pl_op;4646 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
...@@ -4588,17 +4650,10 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4588,17 +4650,10 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
4588 const mulend2 = try f.resolveInst(extra.rhs);4650 const mulend2 = try f.resolveInst(extra.rhs);
4589 const addend = try f.resolveInst(pl_op.operand);4651 const addend = try f.resolveInst(pl_op.operand);
4590 const writer = f.object.writer();4652 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 };
4599 const local = try f.allocLocal(inst_ty, .Const);4653 const local = try f.allocLocal(inst_ty, .Const);
4600 try writer.writeAll(" = ");4654 try writer.writeAll(" = ");
4601 try writer.print("{s}(", .{fn_name});4655 try f.renderFloatFnName("fma", inst_ty);
4656 try writer.writeByte('(');
4602 try f.writeCValue(writer, mulend1);4657 try f.writeCValue(writer, mulend1);
4603 try writer.writeAll(", ");4658 try writer.writeAll(", ");
4604 try f.writeCValue(writer, mulend2);4659 try f.writeCValue(writer, mulend2);
test/behavior/floatop.zig-2
...@@ -571,7 +571,6 @@ test "negation f32" {...@@ -571,7 +571,6 @@ test "negation f32" {
571 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO571 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
573 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO573 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO574 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
576575
577 const S = struct {576 const S = struct {
...@@ -593,7 +592,6 @@ test "negation f64" {...@@ -593,7 +592,6 @@ test "negation f64" {
593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO592 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO594 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
597595
598 const S = struct {596 const S = struct {
599 fn doTheTest() !void {597 fn doTheTest() !void {
test/behavior/math.zig-2
...@@ -376,7 +376,6 @@ fn testBinaryNot(x: u16) !void {...@@ -376,7 +376,6 @@ fn testBinaryNot(x: u16) !void {
376}376}
377377
378test "division" {378test "division" {
379 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
...@@ -1706,7 +1705,6 @@ test "absFloat" {...@@ -1706,7 +1705,6 @@ test "absFloat" {
1706 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1705 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1707 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1706 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1708 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1707 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1709 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
17101708
1711 try testAbsFloat();1709 try testAbsFloat();
1712 comptime try testAbsFloat();1710 comptime try testAbsFloat();