aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-06 15:23:21 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-06 16:11:39 -0700
commit71b8760d3b145c92dc6e331aefff7dac5cabebeb (patch)
tree66b92748616634b689eb5c984f143042132d5e6c /src/Sema.zig
parent6637335981f7179b449fced78cfd4052b1618051 (diff)
downloadzig-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/Sema.zig')
-rw-r--r--src/Sema.zig81
1 files changed, 40 insertions, 41 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 4ef20a99ba..019a635123 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -13525,48 +13525,26 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
const mulend2_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
const addend_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node };
- const mulend1 = sema.resolveInst(extra.mulend1);
- const mulend2 = sema.resolveInst(extra.mulend2);
const addend = sema.resolveInst(extra.addend);
- // All args have the same type
- const ty = sema.typeOf(mulend1);
- switch (ty.zigTypeTag()) {
- .ComptimeFloat, .Float => {},
- .Vector => {
- const scalar_ty = ty.scalarType();
- switch (scalar_ty.zigTypeTag()) {
- .ComptimeFloat, .Float => {},
- else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{scalar_ty}),
- }
- },
- else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty}),
- }
+ const ty = sema.typeOf(addend);
+ const mulend1 = try sema.coerce(block, ty, sema.resolveInst(extra.mulend1), mulend1_src);
+ const mulend2 = try sema.coerce(block, ty, sema.resolveInst(extra.mulend2), mulend2_src);
const target = sema.mod.getTarget();
+
switch (ty.zigTypeTag()) {
.ComptimeFloat, .Float => {
const maybe_mulend1 = try sema.resolveMaybeUndefVal(block, mulend1_src, mulend1);
const maybe_mulend2 = try sema.resolveMaybeUndefVal(block, mulend2_src, mulend2);
const maybe_addend = try sema.resolveMaybeUndefVal(block, addend_src, addend);
- if (maybe_mulend1) |mulend1_val| {
- if (mulend1_val.isUndef())
- return sema.addConstUndef(ty);
- }
-
- if (maybe_mulend2) |mulend2_val| {
- if (mulend2_val.isUndef())
- return sema.addConstUndef(ty);
- }
-
- if (maybe_addend) |addend_val| {
- if (addend_val.isUndef())
- return sema.addConstUndef(ty);
- }
-
- if (maybe_mulend1) |mulend1_val| {
+ const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
if (maybe_mulend2) |mulend2_val| {
+ if (mulend2_val.isUndef()) return sema.addConstUndef(ty);
+
if (maybe_addend) |addend_val| {
+ if (addend_val.isUndef()) return sema.addConstUndef(ty);
+
const result_val = try Value.mulAdd(
ty,
mulend1_val,
@@ -13576,25 +13554,46 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
target,
);
return sema.addConstant(ty, result_val);
+ } else {
+ break :rs addend_src;
}
+ } else {
+ if (maybe_addend) |addend_val| {
+ if (addend_val.isUndef()) return sema.addConstUndef(ty);
+ }
+ break :rs mulend2_src;
}
- }
+ } else rs: {
+ if (maybe_mulend2) |mulend2_val| {
+ if (mulend2_val.isUndef()) return sema.addConstUndef(ty);
+ }
+ if (maybe_addend) |addend_val| {
+ if (addend_val.isUndef()) return sema.addConstUndef(ty);
+ }
+ break :rs mulend1_src;
+ };
- try sema.requireRuntimeBlock(block, src);
+ try sema.requireRuntimeBlock(block, runtime_src);
return block.addInst(.{
.tag = .mul_add,
- .data = .{ .ty_pl = .{
- .ty = try sema.addType(ty),
- .payload = try sema.addExtra(Air.MulAdd{
- .mulend1 = mulend1,
- .mulend2 = mulend2,
- .addend = addend,
+ .data = .{ .pl_op = .{
+ .operand = addend,
+ .payload = try sema.addExtra(Air.Bin{
+ .lhs = mulend1,
+ .rhs = mulend2,
}),
} },
});
},
- .Vector => return sema.fail(block, src, "TODO: implement @mulAdd for vectors", .{}),
- else => unreachable,
+ .Vector => {
+ const scalar_ty = ty.scalarType();
+ switch (scalar_ty.zigTypeTag()) {
+ .ComptimeFloat, .Float => {},
+ else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{scalar_ty}),
+ }
+ return sema.fail(block, src, "TODO: implement @mulAdd for vectors", .{});
+ },
+ else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty}),
}
}