mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 06:15:21 +00:00
cbe: implement some float ops
This commit is contained in:
parent
b48417aed2
commit
6921b0a850
@ -336,6 +336,26 @@ pub const Function = struct {
|
||||
fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
|
||||
return f.object.dg.fmtIntLiteral(ty, val);
|
||||
}
|
||||
|
||||
fn renderFloatFnName(f: *Function, fn_name: []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);
|
||||
const writer = f.object.writer();
|
||||
if (!is_longdouble and float_bits == 80) {
|
||||
try writer.writeAll("__");
|
||||
}
|
||||
try writer.writeAll(fn_name);
|
||||
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`.
|
||||
@ -2076,8 +2096,17 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
||||
.sub => try airBinOp (f, inst, " - "),
|
||||
.mul => try airBinOp (f, inst, " * "),
|
||||
.div_float, .div_exact => try airBinOp( f, inst, " / "),
|
||||
.rem => try airBinOp( f, inst, " % "),
|
||||
|
||||
.rem => blk: {
|
||||
const bin_op = f.air.instructions.items(.data)[inst].bin_op;
|
||||
const lhs_ty = f.air.typeOf(bin_op.lhs);
|
||||
// For binary operations @TypeOf(lhs)==@TypeOf(rhs),
|
||||
// so we only check one.
|
||||
break :blk if (lhs_ty.isInt())
|
||||
try airBinOp(f, inst, " % ")
|
||||
else
|
||||
try airBinFloatOp(f, inst, "fmod"); // yes, @rem() => fmod()
|
||||
},
|
||||
.div_trunc => blk: {
|
||||
const bin_op = f.air.instructions.items(.data)[inst].bin_op;
|
||||
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
|
||||
.floor,
|
||||
.ceil,
|
||||
.round,
|
||||
.trunc_float,
|
||||
=> |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}),
|
||||
=> |tag| try airUnFloatOp(f, inst, @tagName(tag)),
|
||||
.trunc_float => try airUnFloatOp(f, inst, "trunc"),
|
||||
|
||||
.mul_add => try airMulAdd(f, inst),
|
||||
|
||||
@ -4573,12 +4602,45 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
const operand = try f.resolveInst(un_op);
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
try writer.writeByte('-');
|
||||
try writer.writeAll(" = -");
|
||||
try f.writeCValue(writer, operand);
|
||||
try writer.writeAll(";\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
|
||||
if (f.liveness.isUnused(inst)) return CValue.none;
|
||||
const un_op = f.air.instructions.items(.data)[inst].un_op;
|
||||
const writer = f.object.writer();
|
||||
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.renderFloatFnName(fn_name, inst_ty);
|
||||
try writer.writeByte('(');
|
||||
try f.writeCValue(writer, operand);
|
||||
try writer.writeAll(");\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
|
||||
if (f.liveness.isUnused(inst)) return CValue.none;
|
||||
const bin_op = f.air.instructions.items(.data)[inst].bin_op;
|
||||
const writer = f.object.writer();
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
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.renderFloatFnName(fn_name, inst_ty);
|
||||
try writer.writeByte('(');
|
||||
try f.writeCValue(writer, lhs);
|
||||
try writer.writeAll(", ");
|
||||
try f.writeCValue(writer, rhs);
|
||||
try writer.writeAll(");\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
if (f.liveness.isUnused(inst)) return CValue.none;
|
||||
const pl_op = f.air.instructions.items(.data)[inst].pl_op;
|
||||
@ -4588,17 +4650,10 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const mulend2 = try f.resolveInst(extra.rhs);
|
||||
const addend = try f.resolveInst(pl_op.operand);
|
||||
const writer = f.object.writer();
|
||||
const target = f.object.dg.module.getTarget();
|
||||
const fn_name = switch (inst_ty.floatBits(target)) {
|
||||
16, 32 => "fmaf",
|
||||
64 => "fma",
|
||||
80 => if (CType.longdouble.sizeInBits(target) == 80) "fmal" else "__fmax",
|
||||
128 => if (CType.longdouble.sizeInBits(target) == 128) "fmal" else "fmaq",
|
||||
else => unreachable,
|
||||
};
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
try writer.writeAll(" = ");
|
||||
try writer.print("{s}(", .{fn_name});
|
||||
try f.renderFloatFnName("fma", inst_ty);
|
||||
try writer.writeByte('(');
|
||||
try f.writeCValue(writer, mulend1);
|
||||
try writer.writeAll(", ");
|
||||
try f.writeCValue(writer, mulend2);
|
||||
|
||||
@ -571,7 +571,6 @@ test "negation f32" {
|
||||
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 {
|
||||
@ -593,7 +592,6 @@ test "negation f64" {
|
||||
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_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
|
||||
@ -376,7 +376,6 @@ fn testBinaryNot(x: u16) !void {
|
||||
}
|
||||
|
||||
test "division" {
|
||||
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_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
@ -1706,7 +1705,6 @@ test "absFloat" {
|
||||
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 testAbsFloat();
|
||||
comptime try testAbsFloat();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user