| author | |
| committer | |
| log | 6a29646a553a93fc6a4cbf0fee5fa5362483c326 |
| tree | f19368082978b5004e65707cdf4c60c786617db0 |
| parent | 1606717b5fed83ee64ba1a91e55248e07a51afa6 |
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 | 356 | /// Base 10 logarithm of a floating point number. |
| 357 | 357 | /// Uses the `un_op` field. |
| 358 | 358 | log10, |
| 359 | /// Aboslute value of a floating point number. | |
| 360 | /// Uses the `un_op` field. | |
| 361 | fabs, | |
| 359 | /// Aboslute value of an integer, floating point number or vector. | |
| 360 | /// Result type is always unsigned if the operand is an integer. | |
| 361 | /// Uses the `ty_op` field. | |
| 362 | abs, | |
| 362 | 363 | /// Floor: rounds a floating pointer number down to the nearest integer. |
| 363 | 364 | /// Uses the `un_op` field. |
| 364 | 365 | floor, |
| ... | ... | @@ -1279,7 +1280,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1279 | 1280 | .log, |
| 1280 | 1281 | .log2, |
| 1281 | 1282 | .log10, |
| 1282 | .fabs, | |
| 1283 | 1283 | .floor, |
| 1284 | 1284 | .ceil, |
| 1285 | 1285 | .round, |
| ... | ... | @@ -1384,6 +1384,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1384 | 1384 | .addrspace_cast, |
| 1385 | 1385 | .c_va_arg, |
| 1386 | 1386 | .c_va_copy, |
| 1387 | .abs, | |
| 1387 | 1388 | => return air.getRefType(datas[inst].ty_op.ty), |
| 1388 | 1389 | |
| 1389 | 1390 | .loop, |
| ... | ... | @@ -1697,7 +1698,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1697 | 1698 | .log, |
| 1698 | 1699 | .log2, |
| 1699 | 1700 | .log10, |
| 1700 | .fabs, | |
| 1701 | .abs, | |
| 1701 | 1702 | .floor, |
| 1702 | 1703 | .ceil, |
| 1703 | 1704 | .round, |
src/AstGen.zig+2-2| ... | ... | @@ -2601,7 +2601,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2601 | 2601 | .log, |
| 2602 | 2602 | .log2, |
| 2603 | 2603 | .log10, |
| 2604 | .fabs, | |
| 2604 | .abs, | |
| 2605 | 2605 | .floor, |
| 2606 | 2606 | .ceil, |
| 2607 | 2607 | .trunc, |
| ... | ... | @@ -8385,7 +8385,7 @@ fn builtinCall( |
| 8385 | 8385 | .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), |
| 8386 | 8386 | .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), |
| 8387 | 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 | 8389 | .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), |
| 8390 | 8390 | .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), |
| 8391 | 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 | 929 | .log, |
| 930 | 930 | .log2, |
| 931 | 931 | .log10, |
| 932 | .fabs, | |
| 932 | .abs, | |
| 933 | 933 | .floor, |
| 934 | 934 | .ceil, |
| 935 | 935 | .trunc, |
src/Autodoc.zig+1-1| ... | ... | @@ -1669,7 +1669,7 @@ fn walkInstruction( |
| 1669 | 1669 | .log, |
| 1670 | 1670 | .log2, |
| 1671 | 1671 | .log10, |
| 1672 | .fabs, | |
| 1672 | .abs, | |
| 1673 | 1673 | .floor, |
| 1674 | 1674 | .ceil, |
| 1675 | 1675 | .trunc, |
src/BuiltinFn.zig+3-3| ... | ... | @@ -102,7 +102,7 @@ pub const Tag = enum { |
| 102 | 102 | log, |
| 103 | 103 | log2, |
| 104 | 104 | log10, |
| 105 | fabs, | |
| 105 | abs, | |
| 106 | 106 | floor, |
| 107 | 107 | ceil, |
| 108 | 108 | trunc, |
| ... | ... | @@ -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 | 880 | .param_count = 1, |
| 881 | 881 | }, |
| 882 | 882 | }, |
src/Liveness.zig+2-2| ... | ... | @@ -384,6 +384,7 @@ pub fn categorizeOperand( |
| 384 | 384 | .addrspace_cast, |
| 385 | 385 | .c_va_arg, |
| 386 | 386 | .c_va_copy, |
| 387 | .abs, | |
| 387 | 388 | => { |
| 388 | 389 | const o = air_datas[inst].ty_op; |
| 389 | 390 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); |
| ... | ... | @@ -420,7 +421,6 @@ pub fn categorizeOperand( |
| 420 | 421 | .log, |
| 421 | 422 | .log2, |
| 422 | 423 | .log10, |
| 423 | .fabs, | |
| 424 | 424 | .floor, |
| 425 | 425 | .ceil, |
| 426 | 426 | .round, |
| ... | ... | @@ -1027,6 +1027,7 @@ fn analyzeInst( |
| 1027 | 1027 | .addrspace_cast, |
| 1028 | 1028 | .c_va_arg, |
| 1029 | 1029 | .c_va_copy, |
| 1030 | .abs, | |
| 1030 | 1031 | => { |
| 1031 | 1032 | const o = inst_datas[inst].ty_op; |
| 1032 | 1033 | return analyzeOperands(a, pass, data, inst, .{ o.operand, .none, .none }); |
| ... | ... | @@ -1054,7 +1055,6 @@ fn analyzeInst( |
| 1054 | 1055 | .log, |
| 1055 | 1056 | .log2, |
| 1056 | 1057 | .log10, |
| 1057 | .fabs, | |
| 1058 | 1058 | .floor, |
| 1059 | 1059 | .ceil, |
| 1060 | 1060 | .round, |
src/Liveness/Verify.zig+1-1| ... | ... | @@ -110,6 +110,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 110 | 110 | .addrspace_cast, |
| 111 | 111 | .c_va_arg, |
| 112 | 112 | .c_va_copy, |
| 113 | .abs, | |
| 113 | 114 | => { |
| 114 | 115 | const ty_op = data[inst].ty_op; |
| 115 | 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 | 137 | .log, |
| 137 | 138 | .log2, |
| 138 | 139 | .log10, |
| 139 | .fabs, | |
| 140 | 140 | .floor, |
| 141 | 141 | .ceil, |
| 142 | 142 | .round, |
src/Sema.zig+77-50| ... | ... | @@ -1156,6 +1156,7 @@ fn analyzeBodyInner( |
| 1156 | 1156 | .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), |
| 1157 | 1157 | .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), |
| 1158 | 1158 | .pop_count => try sema.zirBitCount(block, inst, .popcount, Value.popCount), |
| 1159 | .abs => try sema.zirAbs(block, inst), | |
| 1159 | 1160 | |
| 1160 | 1161 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), |
| 1161 | 1162 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), |
| ... | ... | @@ -1166,7 +1167,6 @@ fn analyzeBodyInner( |
| 1166 | 1167 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), |
| 1167 | 1168 | .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2), |
| 1168 | 1169 | .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10), |
| 1169 | .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs), | |
| 1170 | 1170 | .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor), |
| 1171 | 1171 | .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil), |
| 1172 | 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 | 20178 | return block.addUnOp(.error_name, operand); |
| 20179 | 20179 | } |
| 20180 | 20180 | |
| 20181 | fn 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 | ||
| 20210 | fn 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 | ||
| 20181 | 20244 | fn zirUnaryMath( |
| 20182 | 20245 | sema: *Sema, |
| 20183 | 20246 | block: *Block, |
| ... | ... | @@ -20193,58 +20256,22 @@ fn zirUnaryMath( |
| 20193 | 20256 | const operand = try sema.resolveInst(inst_data.operand); |
| 20194 | 20257 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20195 | 20258 | const operand_ty = sema.typeOf(operand); |
| 20259 | const scalar_ty = operand_ty.scalarType(mod); | |
| 20196 | 20260 | |
| 20197 | switch (operand_ty.zigTypeTag(mod)) { | |
| 20261 | switch (scalar_ty.zigTypeTag(mod)) { | |
| 20198 | 20262 | .ComptimeFloat, .Float => {}, |
| 20199 | .Vector => { | |
| 20200 | const scalar_ty = operand_ty.scalarType(mod); | |
| 20201 | switch (scalar_ty.zigTypeTag(mod)) { | |
| 20202 | .ComptimeFloat, .Float => {}, | |
| 20203 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}), | |
| 20204 | } | |
| 20205 | }, | |
| 20206 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 20263 | else => return sema.fail( | |
| 20264 | block, | |
| 20265 | operand_src, | |
| 20266 | "expected vector of floats or float type, found '{}'", | |
| 20267 | .{operand_ty.fmt(sema.mod)}, | |
| 20268 | ), | |
| 20207 | 20269 | } |
| 20208 | 20270 | |
| 20209 | switch (operand_ty.zigTypeTag(mod)) { | |
| 20210 | .Vector => { | |
| 20211 | const scalar_ty = operand_ty.scalarType(mod); | |
| 20212 | const vec_len = operand_ty.vectorLen(mod); | |
| 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 | } | |
| 20271 | return (try sema.maybeConstantUnaryMath(operand, operand_ty, eval)) orelse { | |
| 20272 | try sema.requireRuntimeBlock(block, operand_src, null); | |
| 20273 | return block.addUnOp(air_tag, operand); | |
| 20274 | }; | |
| 20248 | 20275 | } |
| 20249 | 20276 | |
| 20250 | 20277 | fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -37503,7 +37530,7 @@ fn float128IntPartToBigInt( |
| 37503 | 37530 | float: f128, |
| 37504 | 37531 | ) !std.math.big.int.Managed { |
| 37505 | 37532 | const is_negative = std.math.signbit(float); |
| 37506 | const floored = @floor(@fabs(float)); | |
| 37533 | const floored = @floor(@abs(float)); | |
| 37507 | 37534 | |
| 37508 | 37535 | var rational = try std.math.big.Rational.init(arena); |
| 37509 | 37536 | defer rational.q.deinit(); |
src/Zir.zig+5-5| ... | ... | @@ -846,8 +846,8 @@ pub const Inst = struct { |
| 846 | 846 | log2, |
| 847 | 847 | /// Implement builtin `@log10`. Uses `un_node`. |
| 848 | 848 | log10, |
| 849 | /// Implement builtin `@fabs`. Uses `un_node`. | |
| 850 | fabs, | |
| 849 | /// Implement builtin `@abs`. Uses `un_node`. | |
| 850 | abs, | |
| 851 | 851 | /// Implement builtin `@floor`. Uses `un_node`. |
| 852 | 852 | floor, |
| 853 | 853 | /// Implement builtin `@ceil`. Uses `un_node`. |
| ... | ... | @@ -1198,7 +1198,7 @@ pub const Inst = struct { |
| 1198 | 1198 | .log, |
| 1199 | 1199 | .log2, |
| 1200 | 1200 | .log10, |
| 1201 | .fabs, | |
| 1201 | .abs, | |
| 1202 | 1202 | .floor, |
| 1203 | 1203 | .ceil, |
| 1204 | 1204 | .trunc, |
| ... | ... | @@ -1493,7 +1493,7 @@ pub const Inst = struct { |
| 1493 | 1493 | .log, |
| 1494 | 1494 | .log2, |
| 1495 | 1495 | .log10, |
| 1496 | .fabs, | |
| 1496 | .abs, | |
| 1497 | 1497 | .floor, |
| 1498 | 1498 | .ceil, |
| 1499 | 1499 | .trunc, |
| ... | ... | @@ -1756,7 +1756,7 @@ pub const Inst = struct { |
| 1756 | 1756 | .log = .un_node, |
| 1757 | 1757 | .log2 = .un_node, |
| 1758 | 1758 | .log10 = .un_node, |
| 1759 | .fabs = .un_node, | |
| 1759 | .abs = .un_node, | |
| 1760 | 1760 | .floor = .un_node, |
| 1761 | 1761 | .ceil = .un_node, |
| 1762 | 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 | 713 | .log, |
| 714 | 714 | .log2, |
| 715 | 715 | .log10, |
| 716 | .fabs, | |
| 717 | 716 | .floor, |
| 718 | 717 | .ceil, |
| 719 | 718 | .round, |
| ... | ... | @@ -788,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 788 | 787 | .clz => try self.airClz(inst), |
| 789 | 788 | .ctz => try self.airCtz(inst), |
| 790 | 789 | .popcount => try self.airPopcount(inst), |
| 790 | .abs => try self.airAbs(inst), | |
| 791 | 791 | .byte_swap => try self.airByteSwap(inst), |
| 792 | 792 | .bit_reverse => try self.airBitReverse(inst), |
| 793 | 793 | .tag_name => try self.airTagName(inst), |
| ... | ... | @@ -3550,6 +3550,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 3550 | 3550 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3551 | 3551 | } |
| 3552 | 3552 | |
| 3553 | fn 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 | ||
| 3553 | 3559 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 3554 | 3560 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3555 | 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 | 699 | .log, |
| 700 | 700 | .log2, |
| 701 | 701 | .log10, |
| 702 | .fabs, | |
| 703 | 702 | .floor, |
| 704 | 703 | .ceil, |
| 705 | 704 | .round, |
| ... | ... | @@ -774,6 +773,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 774 | 773 | .clz => try self.airClz(inst), |
| 775 | 774 | .ctz => try self.airCtz(inst), |
| 776 | 775 | .popcount => try self.airPopcount(inst), |
| 776 | .abs => try self.airAbs(inst), | |
| 777 | 777 | .byte_swap => try self.airByteSwap(inst), |
| 778 | 778 | .bit_reverse => try self.airBitReverse(inst), |
| 779 | 779 | .tag_name => try self.airTagName(inst), |
| ... | ... | @@ -2591,6 +2591,13 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 2591 | 2591 | // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2592 | 2592 | } |
| 2593 | 2593 | |
| 2594 | fn 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 | ||
| 2594 | 2601 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 2595 | 2602 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2596 | 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 | 523 | .log, |
| 524 | 524 | .log2, |
| 525 | 525 | .log10, |
| 526 | .fabs, | |
| 527 | 526 | .floor, |
| 528 | 527 | .ceil, |
| 529 | 528 | .round, |
| ... | ... | @@ -607,6 +606,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 607 | 606 | .clz => try self.airClz(inst), |
| 608 | 607 | .ctz => try self.airCtz(inst), |
| 609 | 608 | .popcount => try self.airPopcount(inst), |
| 609 | .abs => try self.airAbs(inst), | |
| 610 | 610 | .byte_swap => try self.airByteSwap(inst), |
| 611 | 611 | .bit_reverse => try self.airBitReverse(inst), |
| 612 | 612 | .tag_name => try self.airTagName(inst), |
| ... | ... | @@ -1447,6 +1447,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1447 | 1447 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1448 | 1448 | } |
| 1449 | 1449 | |
| 1450 | fn 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 | ||
| 1450 | 1456 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 1451 | 1457 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1452 | 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 | 543 | .log, |
| 544 | 544 | .log2, |
| 545 | 545 | .log10, |
| 546 | .fabs, | |
| 546 | .abs, | |
| 547 | 547 | .floor, |
| 548 | 548 | .ceil, |
| 549 | 549 | .round, |
src/arch/wasm/CodeGen.zig+78-1| ... | ... | @@ -1866,13 +1866,14 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1866 | 1866 | .log => func.airUnaryFloatOp(inst, .log), |
| 1867 | 1867 | .log2 => func.airUnaryFloatOp(inst, .log2), |
| 1868 | 1868 | .log10 => func.airUnaryFloatOp(inst, .log10), |
| 1869 | .fabs => func.airUnaryFloatOp(inst, .fabs), | |
| 1870 | 1869 | .floor => func.airUnaryFloatOp(inst, .floor), |
| 1871 | 1870 | .ceil => func.airUnaryFloatOp(inst, .ceil), |
| 1872 | 1871 | .round => func.airUnaryFloatOp(inst, .round), |
| 1873 | 1872 | .trunc_float => func.airUnaryFloatOp(inst, .trunc), |
| 1874 | 1873 | .neg => func.airUnaryFloatOp(inst, .neg), |
| 1875 | 1874 | |
| 1875 | .abs => func.airAbs(inst), | |
| 1876 | ||
| 1876 | 1877 | .add_with_overflow => func.airAddSubWithOverflow(inst, .add), |
| 1877 | 1878 | .sub_with_overflow => func.airAddSubWithOverflow(inst, .sub), |
| 1878 | 1879 | .shl_with_overflow => func.airShlWithOverflow(inst), |
| ... | ... | @@ -2786,6 +2787,82 @@ const FloatOp = enum { |
| 2786 | 2787 | } |
| 2787 | 2788 | }; |
| 2788 | 2789 | |
| 2790 | fn 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 | ||
| 2789 | 2866 | fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void { |
| 2790 | 2867 | const un_op = func.air.instructions.items(.data)[inst].un_op; |
| 2791 | 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 | 1809 | .round, |
| 1810 | 1810 | => try self.airUnaryMath(inst), |
| 1811 | 1811 | |
| 1812 | .floor => try self.airRound(inst, 0b1_0_01), | |
| 1813 | .ceil => try self.airRound(inst, 0b1_0_10), | |
| 1812 | .floor => try self.airRound(inst, 0b1_0_01), | |
| 1813 | .ceil => try self.airRound(inst, 0b1_0_10), | |
| 1814 | 1814 | .trunc_float => try self.airRound(inst, 0b1_0_11), |
| 1815 | .sqrt => try self.airSqrt(inst), | |
| 1816 | .neg, .fabs => try self.airFloatSign(inst), | |
| 1815 | .sqrt => try self.airSqrt(inst), | |
| 1816 | .neg => try self.airFloatSign(inst), | |
| 1817 | ||
| 1818 | .abs => try self.airAbs(inst), | |
| 1817 | 1819 | |
| 1818 | 1820 | .add_with_overflow => try self.airAddSubWithOverflow(inst), |
| 1819 | 1821 | .sub_with_overflow => try self.airAddSubWithOverflow(inst), |
| ... | ... | @@ -4885,28 +4887,26 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4885 | 4887 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 4886 | 4888 | } |
| 4887 | 4889 | |
| 4888 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | |
| 4890 | fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { | |
| 4889 | 4891 | const mod = self.bin_file.options.module.?; |
| 4890 | 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 | 4893 | const abi_size: u32 = switch (ty.abiSize(mod)) { |
| 4894 | 4894 | 1...16 => 16, |
| 4895 | 4895 | 17...32 => 32, |
| 4896 | else => return self.fail("TODO implement airFloatSign for {}", .{ | |
| 4896 | else => return self.fail("TODO implement floatSign for {}", .{ | |
| 4897 | 4897 | ty.fmt(mod), |
| 4898 | 4898 | }), |
| 4899 | 4899 | }; |
| 4900 | 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 | 4902 | ty.fmt(mod), |
| 4903 | 4903 | }); |
| 4904 | 4904 | |
| 4905 | const src_mcv = try self.resolveInst(un_op); | |
| 4905 | const src_mcv = try self.resolveInst(operand); | |
| 4906 | 4906 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 4907 | 4907 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 4908 | 4908 | |
| 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 | 4910 | src_mcv |
| 4911 | 4911 | else if (self.hasFeature(.avx)) |
| 4912 | 4912 | .{ .register = try self.register_manager.allocReg(inst, sse) } |
| ... | ... | @@ -4923,7 +4923,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4923 | 4923 | |
| 4924 | 4924 | const sign_val = switch (tag) { |
| 4925 | 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 | 4927 | else => unreachable, |
| 4928 | 4928 | }; |
| 4929 | 4929 | |
| ... | ... | @@ -4939,24 +4939,24 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4939 | 4939 | switch (scalar_bits) { |
| 4940 | 4940 | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { |
| 4941 | 4941 | .neg => .{ .vp_, .xor }, |
| 4942 | .fabs => .{ .vp_, .@"and" }, | |
| 4942 | .abs => .{ .vp_, .@"and" }, | |
| 4943 | 4943 | else => unreachable, |
| 4944 | 4944 | } else switch (tag) { |
| 4945 | 4945 | .neg => .{ .v_ps, .xor }, |
| 4946 | .fabs => .{ .v_ps, .@"and" }, | |
| 4946 | .abs => .{ .v_ps, .@"and" }, | |
| 4947 | 4947 | else => unreachable, |
| 4948 | 4948 | }, |
| 4949 | 4949 | 32 => switch (tag) { |
| 4950 | 4950 | .neg => .{ .v_ps, .xor }, |
| 4951 | .fabs => .{ .v_ps, .@"and" }, | |
| 4951 | .abs => .{ .v_ps, .@"and" }, | |
| 4952 | 4952 | else => unreachable, |
| 4953 | 4953 | }, |
| 4954 | 4954 | 64 => switch (tag) { |
| 4955 | 4955 | .neg => .{ .v_pd, .xor }, |
| 4956 | .fabs => .{ .v_pd, .@"and" }, | |
| 4956 | .abs => .{ .v_pd, .@"and" }, | |
| 4957 | 4957 | else => unreachable, |
| 4958 | 4958 | }, |
| 4959 | 80 => return self.fail("TODO implement airFloatSign for {}", .{ | |
| 4959 | 80 => return self.fail("TODO implement floatSign for {}", .{ | |
| 4960 | 4960 | ty.fmt(self.bin_file.options.module.?), |
| 4961 | 4961 | }), |
| 4962 | 4962 | else => unreachable, |
| ... | ... | @@ -4971,20 +4971,20 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4971 | 4971 | switch (scalar_bits) { |
| 4972 | 4972 | 16, 128 => switch (tag) { |
| 4973 | 4973 | .neg => .{ .p_, .xor }, |
| 4974 | .fabs => .{ .p_, .@"and" }, | |
| 4974 | .abs => .{ .p_, .@"and" }, | |
| 4975 | 4975 | else => unreachable, |
| 4976 | 4976 | }, |
| 4977 | 4977 | 32 => switch (tag) { |
| 4978 | 4978 | .neg => .{ ._ps, .xor }, |
| 4979 | .fabs => .{ ._ps, .@"and" }, | |
| 4979 | .abs => .{ ._ps, .@"and" }, | |
| 4980 | 4980 | else => unreachable, |
| 4981 | 4981 | }, |
| 4982 | 4982 | 64 => switch (tag) { |
| 4983 | 4983 | .neg => .{ ._pd, .xor }, |
| 4984 | .fabs => .{ ._pd, .@"and" }, | |
| 4984 | .abs => .{ ._pd, .@"and" }, | |
| 4985 | 4985 | else => unreachable, |
| 4986 | 4986 | }, |
| 4987 | 80 => return self.fail("TODO implement airFloatSign for {}", .{ | |
| 4987 | 80 => return self.fail("TODO implement floatSign for {}", .{ | |
| 4988 | 4988 | ty.fmt(self.bin_file.options.module.?), |
| 4989 | 4989 | }), |
| 4990 | 4990 | else => unreachable, |
| ... | ... | @@ -4992,7 +4992,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4992 | 4992 | registerAlias(dst_reg, abi_size), |
| 4993 | 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 | ||
| 4998 | fn 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 | } |
| 4997 | 5004 | |
| 4998 | 5005 | fn 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 | 5089 | } |
| 5083 | 5090 | } |
| 5084 | 5091 | |
| 5092 | fn 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 | ||
| 5085 | 5138 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5086 | 5139 | const mod = self.bin_file.options.module.?; |
| 5087 | 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 | 105 | try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)}); |
| 106 | 106 | if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{ |
| 107 | 107 | @as(u8, if (rip.disp < 0) '-' else '+'), |
| 108 | std.math.absCast(rip.disp), | |
| 108 | @abs(rip.disp), | |
| 109 | 109 | }); |
| 110 | 110 | try writer.writeByte(']'); |
| 111 | 111 | }, |
| ... | ... | @@ -140,7 +140,7 @@ pub const Instruction = struct { |
| 140 | 140 | try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')}) |
| 141 | 141 | else if (sib.disp < 0) |
| 142 | 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 | 144 | any = true; |
| 145 | 145 | } |
| 146 | 146 |
src/codegen/c.zig+32-10| ... | ... | @@ -2912,6 +2912,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2912 | 2912 | }, |
| 2913 | 2913 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), |
| 2914 | 2914 | .mod => try airBinBuiltinCall(f, inst, "mod", .none), |
| 2915 | .abs => try airAbs(f, inst), | |
| 2915 | 2916 | |
| 2916 | 2917 | .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits), |
| 2917 | 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 | 2932 | .log => try airUnFloatOp(f, inst, "log"), |
| 2932 | 2933 | .log2 => try airUnFloatOp(f, inst, "log2"), |
| 2933 | 2934 | .log10 => try airUnFloatOp(f, inst, "log10"), |
| 2934 | .fabs => try airUnFloatOp(f, inst, "fabs"), | |
| 2935 | 2935 | .floor => try airUnFloatOp(f, inst, "floor"), |
| 2936 | 2936 | .ceil => try airUnFloatOp(f, inst, "ceil"), |
| 2937 | 2937 | .round => try airUnFloatOp(f, inst, "round"), |
| ... | ... | @@ -7076,23 +7076,35 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7076 | 7076 | return local; |
| 7077 | 7077 | } |
| 7078 | 7078 | |
| 7079 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | |
| 7079 | fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 7080 | 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); | |
| 7082 | 7085 | |
| 7083 | const operand = try f.resolveInst(un_op); | |
| 7084 | try reap(f, inst, &.{un_op}); | |
| 7086 | switch (scalar_ty.zigTypeTag(mod)) { | |
| 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 | } | |
| 7085 | 7096 | |
| 7086 | const inst_ty = f.typeOfIndex(inst); | |
| 7087 | const inst_scalar_ty = inst_ty.scalarType(mod); | |
| 7097 | fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue { | |
| 7098 | const mod = f.object.dg.module; | |
| 7099 | const scalar_ty = ty.scalarType(mod); | |
| 7088 | 7100 | |
| 7089 | 7101 | const writer = f.object.writer(); |
| 7090 | const local = try f.allocLocal(inst, inst_ty); | |
| 7091 | const v = try Vectorize.start(f, inst, writer, inst_ty); | |
| 7102 | const local = try f.allocLocal(inst, ty); | |
| 7103 | const v = try Vectorize.start(f, inst, writer, ty); | |
| 7092 | 7104 | try f.writeCValue(writer, local, .Other); |
| 7093 | 7105 | try v.elem(f, writer); |
| 7094 | 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 | 7108 | try writer.writeByte('('); |
| 7097 | 7109 | try writer.writeAll(operation); |
| 7098 | 7110 | try writer.writeAll(")("); |
| ... | ... | @@ -7104,6 +7116,16 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 7104 | 7116 | return local; |
| 7105 | 7117 | } |
| 7106 | 7118 | |
| 7119 | fn 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 | ||
| 7107 | 7129 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7108 | 7130 | const mod = f.object.dg.module; |
| 7109 | 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 | 4729 | .div_exact => try self.airDivExact(inst, .normal), |
| 4730 | 4730 | .rem => try self.airRem(inst, .normal), |
| 4731 | 4731 | .mod => try self.airMod(inst, .normal), |
| 4732 | .abs => try self.airAbs(inst), | |
| 4732 | 4733 | .ptr_add => try self.airPtrAdd(inst), |
| 4733 | 4734 | .ptr_sub => try self.airPtrSub(inst), |
| 4734 | 4735 | .shl => try self.airShl(inst), |
| ... | ... | @@ -4766,7 +4767,6 @@ pub const FuncGen = struct { |
| 4766 | 4767 | .log => try self.airUnaryOp(inst, .log), |
| 4767 | 4768 | .log2 => try self.airUnaryOp(inst, .log2), |
| 4768 | 4769 | .log10 => try self.airUnaryOp(inst, .log10), |
| 4769 | .fabs => try self.airUnaryOp(inst, .fabs), | |
| 4770 | 4770 | .floor => try self.airUnaryOp(inst, .floor), |
| 4771 | 4771 | .ceil => try self.airUnaryOp(inst, .ceil), |
| 4772 | 4772 | .round => try self.airUnaryOp(inst, .round), |
| ... | ... | @@ -8237,6 +8237,28 @@ pub const FuncGen = struct { |
| 8237 | 8237 | else if (is_signed_int) .ashr else .lshr, lhs, casted_rhs, ""); |
| 8238 | 8238 | } |
| 8239 | 8239 | |
| 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 | 8262 | fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8241 | 8263 | const o = self.dg.object; |
| 8242 | 8264 | const mod = o.module; |
src/print_air.zig+1-1| ... | ... | @@ -188,7 +188,7 @@ const Writer = struct { |
| 188 | 188 | .log, |
| 189 | 189 | .log2, |
| 190 | 190 | .log10, |
| 191 | .fabs, | |
| 191 | .abs, | |
| 192 | 192 | .floor, |
| 193 | 193 | .ceil, |
| 194 | 194 | .round, |
src/print_zir.zig+1-1| ... | ... | @@ -262,7 +262,7 @@ const Writer = struct { |
| 262 | 262 | .log, |
| 263 | 263 | .log2, |
| 264 | 264 | .log10, |
| 265 | .fabs, | |
| 265 | .abs, | |
| 266 | 266 | .floor, |
| 267 | 267 | .ceil, |
| 268 | 268 | .trunc, |
src/type.zig+11| ... | ... | @@ -3197,6 +3197,17 @@ pub const Type = struct { |
| 3197 | 3197 | }; |
| 3198 | 3198 | } |
| 3199 | 3199 | |
| 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 | 3211 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 3201 | 3212 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 3202 | 3213 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |
src/value.zig+40-21| ... | ... | @@ -1989,7 +1989,7 @@ pub const Value = struct { |
| 1989 | 1989 | return 1; |
| 1990 | 1990 | } |
| 1991 | 1991 | |
| 1992 | const w_value = @fabs(scalar); | |
| 1992 | const w_value = @abs(scalar); | |
| 1993 | 1993 | return @divFloor(@as(std.math.big.Limb, @intFromFloat(std.math.log2(w_value))), @typeInfo(std.math.big.Limb).Int.bits) + 1; |
| 1994 | 1994 | } |
| 1995 | 1995 | |
| ... | ... | @@ -3706,36 +3706,55 @@ pub const Value = struct { |
| 3706 | 3706 | } })).toValue(); |
| 3707 | 3707 | } |
| 3708 | 3708 | |
| 3709 | pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | |
| 3710 | if (float_type.zigTypeTag(mod) == .Vector) { | |
| 3711 | const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod)); | |
| 3712 | const scalar_ty = float_type.scalarType(mod); | |
| 3709 | pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { | |
| 3710 | if (ty.zigTypeTag(mod) == .Vector) { | |
| 3711 | const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod)); | |
| 3712 | const scalar_ty = ty.scalarType(mod); | |
| 3713 | 3713 | for (result_data, 0..) |*scalar, i| { |
| 3714 | 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 | 3717 | return (try mod.intern(.{ .aggregate = .{ |
| 3718 | .ty = float_type.toIntern(), | |
| 3718 | .ty = ty.toIntern(), | |
| 3719 | 3719 | .storage = .{ .elems = result_data }, |
| 3720 | 3720 | } })).toValue(); |
| 3721 | 3721 | } |
| 3722 | return fabsScalar(val, float_type, mod); | |
| 3722 | return absScalar(val, ty, mod, arena); | |
| 3723 | 3723 | } |
| 3724 | 3724 | |
| 3725 | pub fn fabsScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value { | |
| 3726 | const target = mod.getTarget(); | |
| 3727 | const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) { | |
| 3728 | 16 => .{ .f16 = @fabs(val.toFloat(f16, mod)) }, | |
| 3729 | 32 => .{ .f32 = @fabs(val.toFloat(f32, mod)) }, | |
| 3730 | 64 => .{ .f64 = @fabs(val.toFloat(f64, mod)) }, | |
| 3731 | 80 => .{ .f80 = @fabs(val.toFloat(f80, mod)) }, | |
| 3732 | 128 => .{ .f128 = @fabs(val.toFloat(f128, mod)) }, | |
| 3725 | pub fn absScalar(val: Value, ty: Type, mod: *Module, arena: Allocator) Allocator.Error!Value { | |
| 3726 | switch (ty.zigTypeTag(mod)) { | |
| 3727 | .Int => { | |
| 3728 | var buffer: Value.BigIntSpace = undefined; | |
| 3729 | var operand_bigint = try val.toBigInt(&buffer, mod).toManaged(arena); | |
| 3730 | operand_bigint.abs(); | |
| 3731 | ||
| 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 | 3756 | else => unreachable, |
| 3734 | }; | |
| 3735 | return (try mod.intern(.{ .float = .{ | |
| 3736 | .ty = float_type.toIntern(), | |
| 3737 | .storage = storage, | |
| 3738 | } })).toValue(); | |
| 3757 | } | |
| 3739 | 3758 | } |
| 3740 | 3759 | |
| 3741 | 3760 | pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |