diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-03-06 15:23:21 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-06 16:11:39 -0700 |
| commit | 71b8760d3b145c92dc6e331aefff7dac5cabebeb (patch) | |
| tree | 66b92748616634b689eb5c984f143042132d5e6c /src/codegen/c.zig | |
| parent | 6637335981f7179b449fced78cfd4052b1618051 (diff) | |
| download | zig-71b8760d3b145c92dc6e331aefff7dac5cabebeb.tar.gz zig-71b8760d3b145c92dc6e331aefff7dac5cabebeb.zip | |
stage2: rework `@mulAdd`
* mul_add AIR instruction: use `pl_op` instead of `ty_pl`. The type is
always the same as the operand; no need to waste bytes redundantly
storing the type.
* AstGen: use coerced_ty for all the operands except for one which we
use to communicate the type.
* Sema: use the correct source location for requireRuntimeBlock in
handling of `@mulAdd`.
* native backends: handle liveness even for the functions that are
TODO.
* C backend: implement `@mulAdd`. It lowers to libc calls.
* LLVM backend: make `@mulAdd` handle all float types.
- improved fptrunc and fpext to handle f80 with compiler-rt calls.
* Value.mulAdd: handle all float types and use the `@mulAdd` builtin.
* behavior tests: revert the changes to testing `@mulAdd`. These
changes broke the test coverage, making it only tested at
compile-time.
Improved f80 support:
* std.math.fma handles f80
* move fma functions from freestanding libc to compiler-rt
- add __fmax and fmal
- make __fmax and fmaq only exported when they don't alias fmal.
- make their linkage weak just like the rest of compiler-rt symbols.
* removed `longDoubleIsF128` and replaced it with `longDoubleIs` which
takes a type as a parameter. The implementation is now more accurate
and handles more targets. Similarly, in stage2 the function
CTypes.sizeInBits is more accurate for long double for more targets.
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index e24ff0a6b0..2a10a8094a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -16,6 +16,7 @@ const trace = @import("../tracy.zig").trace; const LazySrcLoc = Module.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); +const CType = @import("../type.zig").CType; const Mutability = enum { Const, Mut }; const BigIntConst = std.math.big.int.Const; @@ -1635,7 +1636,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .trunc_float, => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}), - .mul_add => return f.fail("TODO: C backend: implement @mulAdd", .{}), + .mul_add => try airMulAdd(f, inst), .add_with_overflow => try airAddWithOverflow(f, inst), .sub_with_overflow => try airSubWithOverflow(f, inst), @@ -3623,6 +3624,35 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { 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; + const extra = f.air.extraData(Air.Bin, pl_op.payload).data; + const inst_ty = f.air.typeOfIndex(inst); + const mulend1 = try f.resolveInst(extra.lhs); + 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.writeCValue(writer, mulend1); + try writer.writeAll(", "); + try f.writeCValue(writer, mulend2); + try writer.writeAll(", "); + try f.writeCValue(writer, addend); + try writer.writeAll(");\n"); + return local; +} + fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { return switch (order) { .Unordered => "memory_order_relaxed", |
