authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2023-07-17 00:16:49+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-27 11:15:53-07:00
log6a29646a553a93fc6a4cbf0fee5fa5362483c326
treef19368082978b5004e65707cdf4c60c786617db0
parent1606717b5fed83ee64ba1a91e55248e07a51afa6

Rename `@fabs` to `@abs` and accept integers

Replaces the @fabs builtin with a new @abs builtins which accepts floats, signed integers and vectors of said types.

22 files changed, 384 insertions(+), 133 deletions(-)

src/Air.zig+6-5
...@@ -356,9 +356,10 @@ pub const Inst = struct {...@@ -356,9 +356,10 @@ pub const Inst = struct {
356 /// Base 10 logarithm of a floating point number.356 /// Base 10 logarithm of a floating point number.
357 /// Uses the `un_op` field.357 /// Uses the `un_op` field.
358 log10,358 log10,
359 /// Aboslute value of a floating point number.359 /// Aboslute value of an integer, floating point number or vector.
360 /// Uses the `un_op` field.360 /// Result type is always unsigned if the operand is an integer.
361 fabs,361 /// Uses the `ty_op` field.
362 abs,
362 /// Floor: rounds a floating pointer number down to the nearest integer.363 /// Floor: rounds a floating pointer number down to the nearest integer.
363 /// Uses the `un_op` field.364 /// Uses the `un_op` field.
364 floor,365 floor,
...@@ -1279,7 +1280,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1279,7 +1280,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1279 .log,1280 .log,
1280 .log2,1281 .log2,
1281 .log10,1282 .log10,
1282 .fabs,
1283 .floor,1283 .floor,
1284 .ceil,1284 .ceil,
1285 .round,1285 .round,
...@@ -1384,6 +1384,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1384,6 +1384,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1384 .addrspace_cast,1384 .addrspace_cast,
1385 .c_va_arg,1385 .c_va_arg,
1386 .c_va_copy,1386 .c_va_copy,
1387 .abs,
1387 => return air.getRefType(datas[inst].ty_op.ty),1388 => return air.getRefType(datas[inst].ty_op.ty),
13881389
1389 .loop,1390 .loop,
...@@ -1697,7 +1698,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1697,7 +1698,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1697 .log,1698 .log,
1698 .log2,1699 .log2,
1699 .log10,1700 .log10,
1700 .fabs,1701 .abs,
1701 .floor,1702 .floor,
1702 .ceil,1703 .ceil,
1703 .round,1704 .round,
src/AstGen.zig+2-2
...@@ -2601,7 +2601,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2601,7 +2601,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2601 .log,2601 .log,
2602 .log2,2602 .log2,
2603 .log10,2603 .log10,
2604 .fabs,2604 .abs,
2605 .floor,2605 .floor,
2606 .ceil,2606 .ceil,
2607 .trunc,2607 .trunc,
...@@ -8385,7 +8385,7 @@ fn builtinCall(...@@ -8385,7 +8385,7 @@ fn builtinCall(
8385 .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log),8385 .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log),
8386 .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2),8386 .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2),
8387 .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10),8387 .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10),
8388 .fabs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .fabs),8388 .abs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .abs),
8389 .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor),8389 .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor),
8390 .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil),8390 .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil),
8391 .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc),8391 .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc),
src/AstRlAnnotate.zig+1-1
...@@ -929,7 +929,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -929,7 +929,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
929 .log,929 .log,
930 .log2,930 .log2,
931 .log10,931 .log10,
932 .fabs,932 .abs,
933 .floor,933 .floor,
934 .ceil,934 .ceil,
935 .trunc,935 .trunc,
src/Autodoc.zig+1-1
...@@ -1669,7 +1669,7 @@ fn walkInstruction(...@@ -1669,7 +1669,7 @@ fn walkInstruction(
1669 .log,1669 .log,
1670 .log2,1670 .log2,
1671 .log10,1671 .log10,
1672 .fabs,1672 .abs,
1673 .floor,1673 .floor,
1674 .ceil,1674 .ceil,
1675 .trunc,1675 .trunc,
src/BuiltinFn.zig+3-3
...@@ -102,7 +102,7 @@ pub const Tag = enum {...@@ -102,7 +102,7 @@ pub const Tag = enum {
102 log,102 log,
103 log2,103 log2,
104 log10,104 log10,
105 fabs,105 abs,
106 floor,106 floor,
107 ceil,107 ceil,
108 trunc,108 trunc,
...@@ -874,9 +874,9 @@ pub const list = list: {...@@ -874,9 +874,9 @@ pub const list = list: {
874 },874 },
875 },875 },
876 .{876 .{
877 "@fabs",877 "@abs",
878 .{878 .{
879 .tag = .fabs,879 .tag = .abs,
880 .param_count = 1,880 .param_count = 1,
881 },881 },
882 },882 },
src/Liveness.zig+2-2
...@@ -384,6 +384,7 @@ pub fn categorizeOperand(...@@ -384,6 +384,7 @@ pub fn categorizeOperand(
384 .addrspace_cast,384 .addrspace_cast,
385 .c_va_arg,385 .c_va_arg,
386 .c_va_copy,386 .c_va_copy,
387 .abs,
387 => {388 => {
388 const o = air_datas[inst].ty_op;389 const o = air_datas[inst].ty_op;
389 if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);390 if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
...@@ -420,7 +421,6 @@ pub fn categorizeOperand(...@@ -420,7 +421,6 @@ pub fn categorizeOperand(
420 .log,421 .log,
421 .log2,422 .log2,
422 .log10,423 .log10,
423 .fabs,
424 .floor,424 .floor,
425 .ceil,425 .ceil,
426 .round,426 .round,
...@@ -1027,6 +1027,7 @@ fn analyzeInst(...@@ -1027,6 +1027,7 @@ fn analyzeInst(
1027 .addrspace_cast,1027 .addrspace_cast,
1028 .c_va_arg,1028 .c_va_arg,
1029 .c_va_copy,1029 .c_va_copy,
1030 .abs,
1030 => {1031 => {
1031 const o = inst_datas[inst].ty_op;1032 const o = inst_datas[inst].ty_op;
1032 return analyzeOperands(a, pass, data, inst, .{ o.operand, .none, .none });1033 return analyzeOperands(a, pass, data, inst, .{ o.operand, .none, .none });
...@@ -1054,7 +1055,6 @@ fn analyzeInst(...@@ -1054,7 +1055,6 @@ fn analyzeInst(
1054 .log,1055 .log,
1055 .log2,1056 .log2,
1056 .log10,1057 .log10,
1057 .fabs,
1058 .floor,1058 .floor,
1059 .ceil,1059 .ceil,
1060 .round,1060 .round,
src/Liveness/Verify.zig+1-1
...@@ -110,6 +110,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -110,6 +110,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
110 .addrspace_cast,110 .addrspace_cast,
111 .c_va_arg,111 .c_va_arg,
112 .c_va_copy,112 .c_va_copy,
113 .abs,
113 => {114 => {
114 const ty_op = data[inst].ty_op;115 const ty_op = data[inst].ty_op;
115 try self.verifyInstOperands(inst, .{ ty_op.operand, .none, .none });116 try self.verifyInstOperands(inst, .{ ty_op.operand, .none, .none });
...@@ -136,7 +137,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -136,7 +137,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
136 .log,137 .log,
137 .log2,138 .log2,
138 .log10,139 .log10,
139 .fabs,
140 .floor,140 .floor,
141 .ceil,141 .ceil,
142 .round,142 .round,
src/Sema.zig+77-50
...@@ -1156,6 +1156,7 @@ fn analyzeBodyInner(...@@ -1156,6 +1156,7 @@ fn analyzeBodyInner(
1156 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),1156 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),
1157 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),1157 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),
1158 .pop_count => try sema.zirBitCount(block, inst, .popcount, Value.popCount),1158 .pop_count => try sema.zirBitCount(block, inst, .popcount, Value.popCount),
1159 .abs => try sema.zirAbs(block, inst),
11591160
1160 .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt),1161 .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt),
1161 .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin),1162 .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin),
...@@ -1166,7 +1167,6 @@ fn analyzeBodyInner(...@@ -1166,7 +1167,6 @@ fn analyzeBodyInner(
1166 .log => try sema.zirUnaryMath(block, inst, .log, Value.log),1167 .log => try sema.zirUnaryMath(block, inst, .log, Value.log),
1167 .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2),1168 .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2),
1168 .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10),1169 .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10),
1169 .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs),
1170 .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor),1170 .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor),
1171 .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil),1171 .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil),
1172 .round => try sema.zirUnaryMath(block, inst, .round, Value.round),1172 .round => try sema.zirUnaryMath(block, inst, .round, Value.round),
...@@ -20178,6 +20178,69 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -20178,6 +20178,69 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
20178 return block.addUnOp(.error_name, operand);20178 return block.addUnOp(.error_name, operand);
20179}20179}
2018020180
20181fn zirAbs(
20182 sema: *Sema,
20183 block: *Block,
20184 inst: Zir.Inst.Index,
20185) CompileError!Air.Inst.Ref {
20186 const mod = sema.mod;
20187 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
20188 const operand = try sema.resolveInst(inst_data.operand);
20189 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20190 const operand_ty = sema.typeOf(operand);
20191 const scalar_ty = operand_ty.scalarType(mod);
20192
20193 const result_ty = switch (scalar_ty.zigTypeTag(mod)) {
20194 .ComptimeFloat, .Float, .ComptimeInt => operand_ty,
20195 .Int => if (scalar_ty.isSignedInt(mod)) try operand_ty.toUnsigned(mod) else return operand,
20196 else => return sema.fail(
20197 block,
20198 operand_src,
20199 "expected integer, float, or vector of either integers or floats, found '{}'",
20200 .{operand_ty.fmt(mod)},
20201 ),
20202 };
20203
20204 return (try sema.maybeConstantUnaryMath(operand, result_ty, Value.abs)) orelse {
20205 try sema.requireRuntimeBlock(block, operand_src, null);
20206 return block.addTyOp(.abs, result_ty, operand);
20207 };
20208}
20209
20210fn maybeConstantUnaryMath(
20211 sema: *Sema,
20212 operand: Air.Inst.Ref,
20213 result_ty: Type,
20214 comptime eval: fn (Value, Type, Allocator, *Module) Allocator.Error!Value,
20215) CompileError!?Air.Inst.Ref {
20216 const mod = sema.mod;
20217 switch (result_ty.zigTypeTag(mod)) {
20218 .Vector => if (try sema.resolveMaybeUndefVal(operand)) |val| {
20219 const scalar_ty = result_ty.scalarType(mod);
20220 const vec_len = result_ty.vectorLen(mod);
20221 if (val.isUndef(mod))
20222 return try mod.undefRef(result_ty);
20223
20224 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20225 for (elems, 0..) |*elem, i| {
20226 const elem_val = try val.elemValue(sema.mod, i);
20227 elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod);
20228 }
20229 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
20230 .ty = result_ty.toIntern(),
20231 .storage = .{ .elems = elems },
20232 } })));
20233 },
20234 else => if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
20235 if (operand_val.isUndef(mod))
20236 return try mod.undefRef(result_ty);
20237 const result_val = try eval(operand_val, result_ty, sema.arena, sema.mod);
20238 return Air.internedToRef(result_val.toIntern());
20239 },
20240 }
20241 return null;
20242}
20243
20181fn zirUnaryMath(20244fn zirUnaryMath(
20182 sema: *Sema,20245 sema: *Sema,
20183 block: *Block,20246 block: *Block,
...@@ -20193,58 +20256,22 @@ fn zirUnaryMath(...@@ -20193,58 +20256,22 @@ fn zirUnaryMath(
20193 const operand = try sema.resolveInst(inst_data.operand);20256 const operand = try sema.resolveInst(inst_data.operand);
20194 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20257 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20195 const operand_ty = sema.typeOf(operand);20258 const operand_ty = sema.typeOf(operand);
20259 const scalar_ty = operand_ty.scalarType(mod);
2019620260
20197 switch (operand_ty.zigTypeTag(mod)) {20261 switch (scalar_ty.zigTypeTag(mod)) {
20198 .ComptimeFloat, .Float => {},20262 .ComptimeFloat, .Float => {},
20199 .Vector => {20263 else => return sema.fail(
20200 const scalar_ty = operand_ty.scalarType(mod);20264 block,
20201 switch (scalar_ty.zigTypeTag(mod)) {20265 operand_src,
20202 .ComptimeFloat, .Float => {},20266 "expected vector of floats or float type, found '{}'",
20203 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}),20267 .{operand_ty.fmt(sema.mod)},
20204 }20268 ),
20205 },
20206 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}),
20207 }20269 }
2020820270
20209 switch (operand_ty.zigTypeTag(mod)) {20271 return (try sema.maybeConstantUnaryMath(operand, operand_ty, eval)) orelse {
20210 .Vector => {20272 try sema.requireRuntimeBlock(block, operand_src, null);
20211 const scalar_ty = operand_ty.scalarType(mod);20273 return block.addUnOp(air_tag, operand);
20212 const vec_len = operand_ty.vectorLen(mod);20274 };
20213 const result_ty = try mod.vectorType(.{
20214 .len = vec_len,
20215 .child = scalar_ty.toIntern(),
20216 });
20217 if (try sema.resolveMaybeUndefVal(operand)) |val| {
20218 if (val.isUndef(mod))
20219 return mod.undefRef(result_ty);
20220
20221 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20222 for (elems, 0..) |*elem, i| {
20223 const elem_val = try val.elemValue(sema.mod, i);
20224 elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod);
20225 }
20226 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
20227 .ty = result_ty.toIntern(),
20228 .storage = .{ .elems = elems },
20229 } })));
20230 }
20231
20232 try sema.requireRuntimeBlock(block, operand_src, null);
20233 return block.addUnOp(air_tag, operand);
20234 },
20235 .ComptimeFloat, .Float => {
20236 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
20237 if (operand_val.isUndef(mod))
20238 return mod.undefRef(operand_ty);
20239 const result_val = try eval(operand_val, operand_ty, sema.arena, sema.mod);
20240 return Air.internedToRef(result_val.toIntern());
20241 }
20242
20243 try sema.requireRuntimeBlock(block, operand_src, null);
20244 return block.addUnOp(air_tag, operand);
20245 },
20246 else => unreachable,
20247 }
20248}20275}
2024920276
20250fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20277fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -37503,7 +37530,7 @@ fn float128IntPartToBigInt(...@@ -37503,7 +37530,7 @@ fn float128IntPartToBigInt(
37503 float: f128,37530 float: f128,
37504) !std.math.big.int.Managed {37531) !std.math.big.int.Managed {
37505 const is_negative = std.math.signbit(float);37532 const is_negative = std.math.signbit(float);
37506 const floored = @floor(@fabs(float));37533 const floored = @floor(@abs(float));
3750737534
37508 var rational = try std.math.big.Rational.init(arena);37535 var rational = try std.math.big.Rational.init(arena);
37509 defer rational.q.deinit();37536 defer rational.q.deinit();
src/Zir.zig+5-5
...@@ -846,8 +846,8 @@ pub const Inst = struct {...@@ -846,8 +846,8 @@ pub const Inst = struct {
846 log2,846 log2,
847 /// Implement builtin `@log10`. Uses `un_node`.847 /// Implement builtin `@log10`. Uses `un_node`.
848 log10,848 log10,
849 /// Implement builtin `@fabs`. Uses `un_node`.849 /// Implement builtin `@abs`. Uses `un_node`.
850 fabs,850 abs,
851 /// Implement builtin `@floor`. Uses `un_node`.851 /// Implement builtin `@floor`. Uses `un_node`.
852 floor,852 floor,
853 /// Implement builtin `@ceil`. Uses `un_node`.853 /// Implement builtin `@ceil`. Uses `un_node`.
...@@ -1198,7 +1198,7 @@ pub const Inst = struct {...@@ -1198,7 +1198,7 @@ pub const Inst = struct {
1198 .log,1198 .log,
1199 .log2,1199 .log2,
1200 .log10,1200 .log10,
1201 .fabs,1201 .abs,
1202 .floor,1202 .floor,
1203 .ceil,1203 .ceil,
1204 .trunc,1204 .trunc,
...@@ -1493,7 +1493,7 @@ pub const Inst = struct {...@@ -1493,7 +1493,7 @@ pub const Inst = struct {
1493 .log,1493 .log,
1494 .log2,1494 .log2,
1495 .log10,1495 .log10,
1496 .fabs,1496 .abs,
1497 .floor,1497 .floor,
1498 .ceil,1498 .ceil,
1499 .trunc,1499 .trunc,
...@@ -1756,7 +1756,7 @@ pub const Inst = struct {...@@ -1756,7 +1756,7 @@ pub const Inst = struct {
1756 .log = .un_node,1756 .log = .un_node,
1757 .log2 = .un_node,1757 .log2 = .un_node,
1758 .log10 = .un_node,1758 .log10 = .un_node,
1759 .fabs = .un_node,1759 .abs = .un_node,
1760 .floor = .un_node,1760 .floor = .un_node,
1761 .ceil = .un_node,1761 .ceil = .un_node,
1762 .trunc = .un_node,1762 .trunc = .un_node,
src/arch/aarch64/CodeGen.zig+7-1
...@@ -713,7 +713,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -713,7 +713,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
713 .log,713 .log,
714 .log2,714 .log2,
715 .log10,715 .log10,
716 .fabs,
717 .floor,716 .floor,
718 .ceil,717 .ceil,
719 .round,718 .round,
...@@ -788,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -788,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
788 .clz => try self.airClz(inst),787 .clz => try self.airClz(inst),
789 .ctz => try self.airCtz(inst),788 .ctz => try self.airCtz(inst),
790 .popcount => try self.airPopcount(inst),789 .popcount => try self.airPopcount(inst),
790 .abs => try self.airAbs(inst),
791 .byte_swap => try self.airByteSwap(inst),791 .byte_swap => try self.airByteSwap(inst),
792 .bit_reverse => try self.airBitReverse(inst),792 .bit_reverse => try self.airBitReverse(inst),
793 .tag_name => try self.airTagName(inst),793 .tag_name => try self.airTagName(inst),
...@@ -3550,6 +3550,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -3550,6 +3550,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
3550 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3550 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3551}3551}
35523552
3553fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
3554 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3555 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch});
3556 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3557}
3558
3553fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {3559fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
3554 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3560 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3555 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch});3561 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch});
src/arch/arm/CodeGen.zig+8-1
...@@ -699,7 +699,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -699,7 +699,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
699 .log,699 .log,
700 .log2,700 .log2,
701 .log10,701 .log10,
702 .fabs,
703 .floor,702 .floor,
704 .ceil,703 .ceil,
705 .round,704 .round,
...@@ -774,6 +773,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -774,6 +773,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
774 .clz => try self.airClz(inst),773 .clz => try self.airClz(inst),
775 .ctz => try self.airCtz(inst),774 .ctz => try self.airCtz(inst),
776 .popcount => try self.airPopcount(inst),775 .popcount => try self.airPopcount(inst),
776 .abs => try self.airAbs(inst),
777 .byte_swap => try self.airByteSwap(inst),777 .byte_swap => try self.airByteSwap(inst),
778 .bit_reverse => try self.airBitReverse(inst),778 .bit_reverse => try self.airBitReverse(inst),
779 .tag_name => try self.airTagName(inst),779 .tag_name => try self.airTagName(inst),
...@@ -2591,6 +2591,13 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -2591,6 +2591,13 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
2591 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2591 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2592}2592}
25932593
2594fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
2595 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2596 _ = ty_op;
2597 return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch});
2598 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2599}
2600
2594fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {2601fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
2595 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2602 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2596 _ = ty_op;2603 _ = ty_op;
src/arch/riscv64/CodeGen.zig+7-1
...@@ -523,7 +523,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -523,7 +523,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
523 .log,523 .log,
524 .log2,524 .log2,
525 .log10,525 .log10,
526 .fabs,
527 .floor,526 .floor,
528 .ceil,527 .ceil,
529 .round,528 .round,
...@@ -607,6 +606,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -607,6 +606,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
607 .clz => try self.airClz(inst),606 .clz => try self.airClz(inst),
608 .ctz => try self.airCtz(inst),607 .ctz => try self.airCtz(inst),
609 .popcount => try self.airPopcount(inst),608 .popcount => try self.airPopcount(inst),
609 .abs => try self.airAbs(inst),
610 .byte_swap => try self.airByteSwap(inst),610 .byte_swap => try self.airByteSwap(inst),
611 .bit_reverse => try self.airBitReverse(inst),611 .bit_reverse => try self.airBitReverse(inst),
612 .tag_name => try self.airTagName(inst),612 .tag_name => try self.airTagName(inst),
...@@ -1447,6 +1447,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -1447,6 +1447,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
1447 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1447 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1448}1448}
14491449
1450fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
1451 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1452 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch});
1453 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1454}
1455
1450fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {1456fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
1451 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1457 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1452 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch});1458 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch});
src/arch/sparc64/CodeGen.zig+1-1
...@@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
543 .log,543 .log,
544 .log2,544 .log2,
545 .log10,545 .log10,
546 .fabs,546 .abs,
547 .floor,547 .floor,
548 .ceil,548 .ceil,
549 .round,549 .round,
src/arch/wasm/CodeGen.zig+78-1
...@@ -1866,13 +1866,14 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1866,13 +1866,14 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1866 .log => func.airUnaryFloatOp(inst, .log),1866 .log => func.airUnaryFloatOp(inst, .log),
1867 .log2 => func.airUnaryFloatOp(inst, .log2),1867 .log2 => func.airUnaryFloatOp(inst, .log2),
1868 .log10 => func.airUnaryFloatOp(inst, .log10),1868 .log10 => func.airUnaryFloatOp(inst, .log10),
1869 .fabs => func.airUnaryFloatOp(inst, .fabs),
1870 .floor => func.airUnaryFloatOp(inst, .floor),1869 .floor => func.airUnaryFloatOp(inst, .floor),
1871 .ceil => func.airUnaryFloatOp(inst, .ceil),1870 .ceil => func.airUnaryFloatOp(inst, .ceil),
1872 .round => func.airUnaryFloatOp(inst, .round),1871 .round => func.airUnaryFloatOp(inst, .round),
1873 .trunc_float => func.airUnaryFloatOp(inst, .trunc),1872 .trunc_float => func.airUnaryFloatOp(inst, .trunc),
1874 .neg => func.airUnaryFloatOp(inst, .neg),1873 .neg => func.airUnaryFloatOp(inst, .neg),
18751874
1875 .abs => func.airAbs(inst),
1876
1876 .add_with_overflow => func.airAddSubWithOverflow(inst, .add),1877 .add_with_overflow => func.airAddSubWithOverflow(inst, .add),
1877 .sub_with_overflow => func.airAddSubWithOverflow(inst, .sub),1878 .sub_with_overflow => func.airAddSubWithOverflow(inst, .sub),
1878 .shl_with_overflow => func.airShlWithOverflow(inst),1879 .shl_with_overflow => func.airShlWithOverflow(inst),
...@@ -2786,6 +2787,82 @@ const FloatOp = enum {...@@ -2786,6 +2787,82 @@ const FloatOp = enum {
2786 }2787 }
2787};2788};
27882789
2790fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2791 const mod = func.bin_file.base.options.module.?;
2792 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
2793 const operand = try func.resolveInst(ty_op.operand);
2794 const ty = func.typeOf(ty_op.operand);
2795 const scalar_ty = ty.scalarType(mod);
2796
2797 switch (scalar_ty.zigTypeTag(mod)) {
2798 .Int => if (ty.zigTypeTag(mod) == .Vector) {
2799 return func.fail("TODO implement airAbs for {}", .{ty.fmt(mod)});
2800 } else {
2801 const int_bits = ty.intInfo(mod).bits;
2802 const wasm_bits = toWasmBits(int_bits) orelse {
2803 return func.fail("TODO: airAbs for signed integers larger than '{d}' bits", .{int_bits});
2804 };
2805
2806 const op = try operand.toLocal(func, ty);
2807
2808 try func.emitWValue(op);
2809 switch (wasm_bits) {
2810 32 => {
2811 if (wasm_bits != int_bits) {
2812 try func.addImm32(wasm_bits - int_bits);
2813 try func.addTag(.i32_shl);
2814 }
2815 try func.addImm32(31);
2816 try func.addTag(.i32_shr_s);
2817
2818 const tmp = try func.allocLocal(ty);
2819 try func.addLabel(.local_tee, tmp.local.value);
2820
2821 try func.emitWValue(op);
2822 try func.addTag(.i32_xor);
2823 try func.emitWValue(tmp);
2824 try func.addTag(.i32_sub);
2825
2826 if (int_bits != wasm_bits) {
2827 try func.emitWValue(WValue{ .imm32 = (@as(u32, 1) << @intCast(int_bits)) - 1 });
2828 try func.addTag(.i32_and);
2829 }
2830 },
2831 64 => {
2832 if (wasm_bits != int_bits) {
2833 try func.addImm64(wasm_bits - int_bits);
2834 try func.addTag(.i64_shl);
2835 }
2836 try func.addImm64(63);
2837 try func.addTag(.i64_shr_s);
2838
2839 const tmp = try func.allocLocal(ty);
2840 try func.addLabel(.local_tee, tmp.local.value);
2841
2842 try func.emitWValue(op);
2843 try func.addTag(.i64_xor);
2844 try func.emitWValue(tmp);
2845 try func.addTag(.i64_sub);
2846
2847 if (int_bits != wasm_bits) {
2848 try func.emitWValue(WValue{ .imm64 = (@as(u64, 1) << @intCast(int_bits)) - 1 });
2849 try func.addTag(.i64_and);
2850 }
2851 },
2852 else => return func.fail("TODO: Implement airAbs for {}", .{ty.fmt(mod)}),
2853 }
2854
2855 const result = try (WValue{ .stack = {} }).toLocal(func, ty);
2856 func.finishAir(inst, result, &.{ty_op.operand});
2857 },
2858 .Float => {
2859 const result = try (try func.floatOp(.fabs, ty, &.{operand})).toLocal(func, ty);
2860 func.finishAir(inst, result, &.{ty_op.operand});
2861 },
2862 else => unreachable,
2863 }
2864}
2865
2789fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void {2866fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void {
2790 const un_op = func.air.instructions.items(.data)[inst].un_op;2867 const un_op = func.air.instructions.items(.data)[inst].un_op;
2791 const operand = try func.resolveInst(un_op);2868 const operand = try func.resolveInst(un_op);
src/arch/x86_64/CodeGen.zig+75-22
...@@ -1809,11 +1809,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1809,11 +1809,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1809 .round,1809 .round,
1810 => try self.airUnaryMath(inst),1810 => try self.airUnaryMath(inst),
18111811
1812 .floor => try self.airRound(inst, 0b1_0_01),1812 .floor => try self.airRound(inst, 0b1_0_01),
1813 .ceil => try self.airRound(inst, 0b1_0_10),1813 .ceil => try self.airRound(inst, 0b1_0_10),
1814 .trunc_float => try self.airRound(inst, 0b1_0_11),1814 .trunc_float => try self.airRound(inst, 0b1_0_11),
1815 .sqrt => try self.airSqrt(inst),1815 .sqrt => try self.airSqrt(inst),
1816 .neg, .fabs => try self.airFloatSign(inst),1816 .neg => try self.airFloatSign(inst),
1817
1818 .abs => try self.airAbs(inst),
18171819
1818 .add_with_overflow => try self.airAddSubWithOverflow(inst),1820 .add_with_overflow => try self.airAddSubWithOverflow(inst),
1819 .sub_with_overflow => try self.airAddSubWithOverflow(inst),1821 .sub_with_overflow => try self.airAddSubWithOverflow(inst),
...@@ -4885,28 +4887,26 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {...@@ -4885,28 +4887,26 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4885 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });4887 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
4886}4888}
48874889
4888fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {4890fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void {
4889 const mod = self.bin_file.options.module.?;4891 const mod = self.bin_file.options.module.?;
4890 const tag = self.air.instructions.items(.tag)[inst];4892 const tag = self.air.instructions.items(.tag)[inst];
4891 const un_op = self.air.instructions.items(.data)[inst].un_op;
4892 const ty = self.typeOf(un_op);
4893 const abi_size: u32 = switch (ty.abiSize(mod)) {4893 const abi_size: u32 = switch (ty.abiSize(mod)) {
4894 1...16 => 16,4894 1...16 => 16,
4895 17...32 => 32,4895 17...32 => 32,
4896 else => return self.fail("TODO implement airFloatSign for {}", .{4896 else => return self.fail("TODO implement floatSign for {}", .{
4897 ty.fmt(mod),4897 ty.fmt(mod),
4898 }),4898 }),
4899 };4899 };
4900 const scalar_bits = ty.scalarType(mod).floatBits(self.target.*);4900 const scalar_bits = ty.scalarType(mod).floatBits(self.target.*);
4901 if (scalar_bits == 80) return self.fail("TODO implement airFloatSign for {}", .{4901 if (scalar_bits == 80) return self.fail("TODO implement floatSign for {}", .{
4902 ty.fmt(mod),4902 ty.fmt(mod),
4903 });4903 });
49044904
4905 const src_mcv = try self.resolveInst(un_op);4905 const src_mcv = try self.resolveInst(operand);
4906 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;4906 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
4907 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);4907 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
49084908
4909 const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))4909 const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, operand, 0, src_mcv))
4910 src_mcv4910 src_mcv
4911 else if (self.hasFeature(.avx))4911 else if (self.hasFeature(.avx))
4912 .{ .register = try self.register_manager.allocReg(inst, sse) }4912 .{ .register = try self.register_manager.allocReg(inst, sse) }
...@@ -4923,7 +4923,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -4923,7 +4923,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
49234923
4924 const sign_val = switch (tag) {4924 const sign_val = switch (tag) {
4925 .neg => try vec_ty.minInt(mod, vec_ty),4925 .neg => try vec_ty.minInt(mod, vec_ty),
4926 .fabs => try vec_ty.maxInt(mod, vec_ty),4926 .abs => try vec_ty.maxInt(mod, vec_ty),
4927 else => unreachable,4927 else => unreachable,
4928 };4928 };
49294929
...@@ -4939,24 +4939,24 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -4939,24 +4939,24 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4939 switch (scalar_bits) {4939 switch (scalar_bits) {
4940 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) {4940 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) {
4941 .neg => .{ .vp_, .xor },4941 .neg => .{ .vp_, .xor },
4942 .fabs => .{ .vp_, .@"and" },4942 .abs => .{ .vp_, .@"and" },
4943 else => unreachable,4943 else => unreachable,
4944 } else switch (tag) {4944 } else switch (tag) {
4945 .neg => .{ .v_ps, .xor },4945 .neg => .{ .v_ps, .xor },
4946 .fabs => .{ .v_ps, .@"and" },4946 .abs => .{ .v_ps, .@"and" },
4947 else => unreachable,4947 else => unreachable,
4948 },4948 },
4949 32 => switch (tag) {4949 32 => switch (tag) {
4950 .neg => .{ .v_ps, .xor },4950 .neg => .{ .v_ps, .xor },
4951 .fabs => .{ .v_ps, .@"and" },4951 .abs => .{ .v_ps, .@"and" },
4952 else => unreachable,4952 else => unreachable,
4953 },4953 },
4954 64 => switch (tag) {4954 64 => switch (tag) {
4955 .neg => .{ .v_pd, .xor },4955 .neg => .{ .v_pd, .xor },
4956 .fabs => .{ .v_pd, .@"and" },4956 .abs => .{ .v_pd, .@"and" },
4957 else => unreachable,4957 else => unreachable,
4958 },4958 },
4959 80 => return self.fail("TODO implement airFloatSign for {}", .{4959 80 => return self.fail("TODO implement floatSign for {}", .{
4960 ty.fmt(self.bin_file.options.module.?),4960 ty.fmt(self.bin_file.options.module.?),
4961 }),4961 }),
4962 else => unreachable,4962 else => unreachable,
...@@ -4971,20 +4971,20 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -4971,20 +4971,20 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4971 switch (scalar_bits) {4971 switch (scalar_bits) {
4972 16, 128 => switch (tag) {4972 16, 128 => switch (tag) {
4973 .neg => .{ .p_, .xor },4973 .neg => .{ .p_, .xor },
4974 .fabs => .{ .p_, .@"and" },4974 .abs => .{ .p_, .@"and" },
4975 else => unreachable,4975 else => unreachable,
4976 },4976 },
4977 32 => switch (tag) {4977 32 => switch (tag) {
4978 .neg => .{ ._ps, .xor },4978 .neg => .{ ._ps, .xor },
4979 .fabs => .{ ._ps, .@"and" },4979 .abs => .{ ._ps, .@"and" },
4980 else => unreachable,4980 else => unreachable,
4981 },4981 },
4982 64 => switch (tag) {4982 64 => switch (tag) {
4983 .neg => .{ ._pd, .xor },4983 .neg => .{ ._pd, .xor },
4984 .fabs => .{ ._pd, .@"and" },4984 .abs => .{ ._pd, .@"and" },
4985 else => unreachable,4985 else => unreachable,
4986 },4986 },
4987 80 => return self.fail("TODO implement airFloatSign for {}", .{4987 80 => return self.fail("TODO implement floatSign for {}", .{
4988 ty.fmt(self.bin_file.options.module.?),4988 ty.fmt(self.bin_file.options.module.?),
4989 }),4989 }),
4990 else => unreachable,4990 else => unreachable,
...@@ -4992,7 +4992,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -4992,7 +4992,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4992 registerAlias(dst_reg, abi_size),4992 registerAlias(dst_reg, abi_size),
4993 sign_mem,4993 sign_mem,
4994 );4994 );
4995 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });4995 return self.finishAir(inst, dst_mcv, .{ operand, .none, .none });
4996}
4997
4998fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4999 const un_op = self.air.instructions.items(.data)[inst].un_op;
5000 const ty = self.typeOf(un_op);
5001
5002 return self.floatSign(inst, un_op, ty);
4996}5003}
49975004
4998fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {5005fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
...@@ -5082,6 +5089,52 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4...@@ -5082,6 +5089,52 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5082 }5089 }
5083}5090}
50845091
5092fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
5093 const mod = self.bin_file.options.module.?;
5094 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5095 const ty = self.typeOf(ty_op.operand);
5096 const scalar_ty = ty.scalarType(mod);
5097
5098 switch (scalar_ty.zigTypeTag(mod)) {
5099 .Int => if (ty.zigTypeTag(mod) == .Vector) {
5100 return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)});
5101 } else {
5102 if (ty.abiSize(mod) > 8) {
5103 return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});
5104 }
5105 const src_mcv = try self.resolveInst(ty_op.operand);
5106 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5107
5108 try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);
5109
5110 const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
5111 switch (src_mcv) {
5112 .register => |val_reg| try self.asmCmovccRegisterRegister(
5113 registerAlias(dst_mcv.register, cmov_abi_size),
5114 registerAlias(val_reg, cmov_abi_size),
5115 .l,
5116 ),
5117 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
5118 registerAlias(dst_mcv.register, cmov_abi_size),
5119 src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
5120 .l,
5121 ),
5122 else => {
5123 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
5124 try self.asmCmovccRegisterRegister(
5125 registerAlias(dst_mcv.register, cmov_abi_size),
5126 registerAlias(val_reg, cmov_abi_size),
5127 .l,
5128 );
5129 },
5130 }
5131 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
5132 },
5133 .Float => return self.floatSign(inst, ty_op.operand, ty),
5134 else => unreachable,
5135 }
5136}
5137
5085fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {5138fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5086 const mod = self.bin_file.options.module.?;5139 const mod = self.bin_file.options.module.?;
5087 const un_op = self.air.instructions.items(.data)[inst].un_op;5140 const un_op = self.air.instructions.items(.data)[inst].un_op;
src/arch/x86_64/encoder.zig+2-2
...@@ -105,7 +105,7 @@ pub const Instruction = struct {...@@ -105,7 +105,7 @@ pub const Instruction = struct {
105 try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)});105 try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)});
106 if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{106 if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{
107 @as(u8, if (rip.disp < 0) '-' else '+'),107 @as(u8, if (rip.disp < 0) '-' else '+'),
108 std.math.absCast(rip.disp),108 @abs(rip.disp),
109 });109 });
110 try writer.writeByte(']');110 try writer.writeByte(']');
111 },111 },
...@@ -140,7 +140,7 @@ pub const Instruction = struct {...@@ -140,7 +140,7 @@ pub const Instruction = struct {
140 try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')})140 try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')})
141 else if (sib.disp < 0)141 else if (sib.disp < 0)
142 try writer.writeByte('-');142 try writer.writeByte('-');
143 try writer.print("0x{x}", .{std.math.absCast(sib.disp)});143 try writer.print("0x{x}", .{@abs(sib.disp)});
144 any = true;144 any = true;
145 }145 }
146146
src/codegen/c.zig+32-10
...@@ -2912,6 +2912,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2912,6 +2912,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2912 },2912 },
2913 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),2913 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),
2914 .mod => try airBinBuiltinCall(f, inst, "mod", .none),2914 .mod => try airBinBuiltinCall(f, inst, "mod", .none),
2915 .abs => try airAbs(f, inst),
29152916
2916 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),2917 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),
2917 .sub_wrap => try airBinBuiltinCall(f, inst, "subw", .bits),2918 .sub_wrap => try airBinBuiltinCall(f, inst, "subw", .bits),
...@@ -2931,7 +2932,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2931,7 +2932,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2931 .log => try airUnFloatOp(f, inst, "log"),2932 .log => try airUnFloatOp(f, inst, "log"),
2932 .log2 => try airUnFloatOp(f, inst, "log2"),2933 .log2 => try airUnFloatOp(f, inst, "log2"),
2933 .log10 => try airUnFloatOp(f, inst, "log10"),2934 .log10 => try airUnFloatOp(f, inst, "log10"),
2934 .fabs => try airUnFloatOp(f, inst, "fabs"),
2935 .floor => try airUnFloatOp(f, inst, "floor"),2935 .floor => try airUnFloatOp(f, inst, "floor"),
2936 .ceil => try airUnFloatOp(f, inst, "ceil"),2936 .ceil => try airUnFloatOp(f, inst, "ceil"),
2937 .round => try airUnFloatOp(f, inst, "round"),2937 .round => try airUnFloatOp(f, inst, "round"),
...@@ -7076,23 +7076,35 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7076,23 +7076,35 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
7076 return local;7076 return local;
7077}7077}
70787078
7079fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {7079fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {
7080 const mod = f.object.dg.module;7080 const mod = f.object.dg.module;
7081 const un_op = f.air.instructions.items(.data)[inst].un_op;7081 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
7082 const operand = try f.resolveInst(ty_op.operand);
7083 const ty = f.typeOf(ty_op.operand);
7084 const scalar_ty = ty.scalarType(mod);
70827085
7083 const operand = try f.resolveInst(un_op);7086 switch (scalar_ty.zigTypeTag(mod)) {
7084 try reap(f, inst, &.{un_op});7087 .Int => if (ty.zigTypeTag(mod) == .Vector) {
7088 return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(mod)});
7089 } else {
7090 return airUnBuiltinCall(f, inst, "abs", .none);
7091 },
7092 .Float => return unFloatOp(f, inst, operand, ty, "fabs"),
7093 else => unreachable,
7094 }
7095}
70857096
7086 const inst_ty = f.typeOfIndex(inst);7097fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue {
7087 const inst_scalar_ty = inst_ty.scalarType(mod);7098 const mod = f.object.dg.module;
7099 const scalar_ty = ty.scalarType(mod);
70887100
7089 const writer = f.object.writer();7101 const writer = f.object.writer();
7090 const local = try f.allocLocal(inst, inst_ty);7102 const local = try f.allocLocal(inst, ty);
7091 const v = try Vectorize.start(f, inst, writer, inst_ty);7103 const v = try Vectorize.start(f, inst, writer, ty);
7092 try f.writeCValue(writer, local, .Other);7104 try f.writeCValue(writer, local, .Other);
7093 try v.elem(f, writer);7105 try v.elem(f, writer);
7094 try writer.writeAll(" = zig_libc_name_");7106 try writer.writeAll(" = zig_libc_name_");
7095 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);7107 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
7096 try writer.writeByte('(');7108 try writer.writeByte('(');
7097 try writer.writeAll(operation);7109 try writer.writeAll(operation);
7098 try writer.writeAll(")(");7110 try writer.writeAll(")(");
...@@ -7104,6 +7116,16 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal...@@ -7104,6 +7116,16 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
7104 return local;7116 return local;
7105}7117}
71067118
7119fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
7120 const un_op = f.air.instructions.items(.data)[inst].un_op;
7121
7122 const operand = try f.resolveInst(un_op);
7123 try reap(f, inst, &.{un_op});
7124
7125 const inst_ty = f.typeOfIndex(inst);
7126 return unFloatOp(f, inst, operand, inst_ty, operation);
7127}
7128
7107fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {7129fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
7108 const mod = f.object.dg.module;7130 const mod = f.object.dg.module;
7109 const bin_op = f.air.instructions.items(.data)[inst].bin_op;7131 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
src/codegen/llvm.zig+23-1
...@@ -4729,6 +4729,7 @@ pub const FuncGen = struct {...@@ -4729,6 +4729,7 @@ pub const FuncGen = struct {
4729 .div_exact => try self.airDivExact(inst, .normal),4729 .div_exact => try self.airDivExact(inst, .normal),
4730 .rem => try self.airRem(inst, .normal),4730 .rem => try self.airRem(inst, .normal),
4731 .mod => try self.airMod(inst, .normal),4731 .mod => try self.airMod(inst, .normal),
4732 .abs => try self.airAbs(inst),
4732 .ptr_add => try self.airPtrAdd(inst),4733 .ptr_add => try self.airPtrAdd(inst),
4733 .ptr_sub => try self.airPtrSub(inst),4734 .ptr_sub => try self.airPtrSub(inst),
4734 .shl => try self.airShl(inst),4735 .shl => try self.airShl(inst),
...@@ -4766,7 +4767,6 @@ pub const FuncGen = struct {...@@ -4766,7 +4767,6 @@ pub const FuncGen = struct {
4766 .log => try self.airUnaryOp(inst, .log),4767 .log => try self.airUnaryOp(inst, .log),
4767 .log2 => try self.airUnaryOp(inst, .log2),4768 .log2 => try self.airUnaryOp(inst, .log2),
4768 .log10 => try self.airUnaryOp(inst, .log10),4769 .log10 => try self.airUnaryOp(inst, .log10),
4769 .fabs => try self.airUnaryOp(inst, .fabs),
4770 .floor => try self.airUnaryOp(inst, .floor),4770 .floor => try self.airUnaryOp(inst, .floor),
4771 .ceil => try self.airUnaryOp(inst, .ceil),4771 .ceil => try self.airUnaryOp(inst, .ceil),
4772 .round => try self.airUnaryOp(inst, .round),4772 .round => try self.airUnaryOp(inst, .round),
...@@ -8237,6 +8237,28 @@ pub const FuncGen = struct {...@@ -8237,6 +8237,28 @@ pub const FuncGen = struct {
8237 else if (is_signed_int) .ashr else .lshr, lhs, casted_rhs, "");8237 else if (is_signed_int) .ashr else .lshr, lhs, casted_rhs, "");
8238 }8238 }
82398239
8240 fn airAbs(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8241 const o = self.dg.object;
8242 const mod = o.module;
8243 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8244 const operand = try self.resolveInst(ty_op.operand);
8245 const operand_ty = self.typeOf(ty_op.operand);
8246 const scalar_ty = operand_ty.scalarType(mod);
8247
8248 switch (scalar_ty.zigTypeTag(mod)) {
8249 .Int => return self.wip.callIntrinsic(
8250 .normal,
8251 .none,
8252 .abs,
8253 &.{try o.lowerType(operand_ty)},
8254 &.{ operand, try o.builder.intValue(.i1, 0) },
8255 "",
8256 ),
8257 .Float => return self.buildFloatOp(.fabs, .normal, operand_ty, 1, .{operand}),
8258 else => unreachable,
8259 }
8260 }
8261
8240 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8262 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8241 const o = self.dg.object;8263 const o = self.dg.object;
8242 const mod = o.module;8264 const mod = o.module;
src/print_air.zig+1-1
...@@ -188,7 +188,7 @@ const Writer = struct {...@@ -188,7 +188,7 @@ const Writer = struct {
188 .log,188 .log,
189 .log2,189 .log2,
190 .log10,190 .log10,
191 .fabs,191 .abs,
192 .floor,192 .floor,
193 .ceil,193 .ceil,
194 .round,194 .round,
src/print_zir.zig+1-1
...@@ -262,7 +262,7 @@ const Writer = struct {...@@ -262,7 +262,7 @@ const Writer = struct {
262 .log,262 .log,
263 .log2,263 .log2,
264 .log10,264 .log10,
265 .fabs,265 .abs,
266 .floor,266 .floor,
267 .ceil,267 .ceil,
268 .trunc,268 .trunc,
src/type.zig+11
...@@ -3197,6 +3197,17 @@ pub const Type = struct {...@@ -3197,6 +3197,17 @@ pub const Type = struct {
3197 };3197 };
3198 }3198 }
31993199
3200 pub fn toUnsigned(ty: Type, mod: *Module) !Type {
3201 return switch (ty.zigTypeTag(mod)) {
3202 .Int => mod.intType(.unsigned, ty.intInfo(mod).bits),
3203 .Vector => try mod.vectorType(.{
3204 .len = ty.vectorLen(mod),
3205 .child = (try ty.childType(mod).toUnsigned(mod)).toIntern(),
3206 }),
3207 else => unreachable,
3208 };
3209 }
3210
3200 pub const @"u1": Type = .{ .ip_index = .u1_type };3211 pub const @"u1": Type = .{ .ip_index = .u1_type };
3201 pub const @"u8": Type = .{ .ip_index = .u8_type };3212 pub const @"u8": Type = .{ .ip_index = .u8_type };
3202 pub const @"u16": Type = .{ .ip_index = .u16_type };3213 pub const @"u16": Type = .{ .ip_index = .u16_type };
src/value.zig+40-21
...@@ -1989,7 +1989,7 @@ pub const Value = struct {...@@ -1989,7 +1989,7 @@ pub const Value = struct {
1989 return 1;1989 return 1;
1990 }1990 }
19911991
1992 const w_value = @fabs(scalar);1992 const w_value = @abs(scalar);
1993 return @divFloor(@as(std.math.big.Limb, @intFromFloat(std.math.log2(w_value))), @typeInfo(std.math.big.Limb).Int.bits) + 1;1993 return @divFloor(@as(std.math.big.Limb, @intFromFloat(std.math.log2(w_value))), @typeInfo(std.math.big.Limb).Int.bits) + 1;
1994 }1994 }
19951995
...@@ -3706,36 +3706,55 @@ pub const Value = struct {...@@ -3706,36 +3706,55 @@ pub const Value = struct {
3706 } })).toValue();3706 } })).toValue();
3707 }3707 }
37083708
3709 pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3709 pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3710 if (float_type.zigTypeTag(mod) == .Vector) {3710 if (ty.zigTypeTag(mod) == .Vector) {
3711 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));3711 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3712 const scalar_ty = float_type.scalarType(mod);3712 const scalar_ty = ty.scalarType(mod);
3713 for (result_data, 0..) |*scalar, i| {3713 for (result_data, 0..) |*scalar, i| {
3714 const elem_val = try val.elemValue(mod, i);3714 const elem_val = try val.elemValue(mod, i);
3715 scalar.* = try (try fabsScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3715 scalar.* = try (try absScalar(elem_val, scalar_ty, mod, arena)).intern(scalar_ty, mod);
3716 }3716 }
3717 return (try mod.intern(.{ .aggregate = .{3717 return (try mod.intern(.{ .aggregate = .{
3718 .ty = float_type.toIntern(),3718 .ty = ty.toIntern(),
3719 .storage = .{ .elems = result_data },3719 .storage = .{ .elems = result_data },
3720 } })).toValue();3720 } })).toValue();
3721 }3721 }
3722 return fabsScalar(val, float_type, mod);3722 return absScalar(val, ty, mod, arena);
3723 }3723 }
37243724
3725 pub fn fabsScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {3725 pub fn absScalar(val: Value, ty: Type, mod: *Module, arena: Allocator) Allocator.Error!Value {
3726 const target = mod.getTarget();3726 switch (ty.zigTypeTag(mod)) {
3727 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {3727 .Int => {
3728 16 => .{ .f16 = @fabs(val.toFloat(f16, mod)) },3728 var buffer: Value.BigIntSpace = undefined;
3729 32 => .{ .f32 = @fabs(val.toFloat(f32, mod)) },3729 var operand_bigint = try val.toBigInt(&buffer, mod).toManaged(arena);
3730 64 => .{ .f64 = @fabs(val.toFloat(f64, mod)) },3730 operand_bigint.abs();
3731 80 => .{ .f80 = @fabs(val.toFloat(f80, mod)) },3731
3732 128 => .{ .f128 = @fabs(val.toFloat(f128, mod)) },3732 return mod.intValue_big(try ty.toUnsigned(mod), operand_bigint.toConst());
3733 },
3734 .ComptimeInt => {
3735 var buffer: Value.BigIntSpace = undefined;
3736 var operand_bigint = try val.toBigInt(&buffer, mod).toManaged(arena);
3737 operand_bigint.abs();
3738
3739 return mod.intValue_big(ty, operand_bigint.toConst());
3740 },
3741 .ComptimeFloat, .Float => {
3742 const target = mod.getTarget();
3743 const storage: InternPool.Key.Float.Storage = switch (ty.floatBits(target)) {
3744 16 => .{ .f16 = @abs(val.toFloat(f16, mod)) },
3745 32 => .{ .f32 = @abs(val.toFloat(f32, mod)) },
3746 64 => .{ .f64 = @abs(val.toFloat(f64, mod)) },
3747 80 => .{ .f80 = @abs(val.toFloat(f80, mod)) },
3748 128 => .{ .f128 = @abs(val.toFloat(f128, mod)) },
3749 else => unreachable,
3750 };
3751 return (try mod.intern(.{ .float = .{
3752 .ty = ty.toIntern(),
3753 .storage = storage,
3754 } })).toValue();
3755 },
3733 else => unreachable,3756 else => unreachable,
3734 };3757 }
3735 return (try mod.intern(.{ .float = .{
3736 .ty = float_type.toIntern(),
3737 .storage = storage,
3738 } })).toValue();
3739 }3758 }
37403759
3741 pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {3760 pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {