| 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,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), |
| 1388 | 1389 | ||
| 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), | ||
| 1159 | 1160 | ||
| 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 | } |
| 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 | fn zirUnaryMath( | 20244 | fn 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); | ||
| 20196 | 20260 | ||
| 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 | } |
| 20208 | 20270 | ||
| 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 | } |
| 20249 | 20276 | ||
| 20250 | fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20277 | fn 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)); |
| 37507 | 37534 | ||
| 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 | } |
| 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 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 3559 | fn 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 | } |
| 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 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 2601 | fn 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 | } |
| 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 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 1456 | fn 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), |
| 1875 | 1874 | ||
| 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 | }; |
| 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 | fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void { | 2866 | fn 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), |
| 1811 | 1811 | ||
| 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), | ||
| 1817 | 1819 | ||
| 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 | } |
| 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 | 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 | }); |
| 4904 | 4904 | ||
| 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); |
| 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 | src_mcv | 4910 | 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 { |
| 4923 | 4923 | ||
| 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 | }; |
| 4929 | 4929 | ||
| ... | @@ -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 | |||
| 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 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void { | 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,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 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | 5138 | fn 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 | } |
| 146 | 146 |
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), | ||
| 2915 | 2916 | ||
| 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 | } |
| 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 | 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); | ||
| 7082 | 7085 | ||
| 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 | } | ||
| 7085 | 7096 | ||
| 7086 | const inst_ty = f.typeOfIndex(inst); | 7097 | fn 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); | ||
| 7088 | 7100 | ||
| 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 | } |
| 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 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 7129 | fn 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 | } |
| 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 | 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 | } |
| 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 | 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 | } |
| 1991 | 1991 | ||
| 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 | } |
| 1995 | 1995 | ||
| ... | @@ -3706,36 +3706,55 @@ pub const Value = struct { | ... | @@ -3706,36 +3706,55 @@ pub const Value = struct { |
| 3706 | } })).toValue(); | 3706 | } })).toValue(); |
| 3707 | } | 3707 | } |
| 3708 | 3708 | ||
| 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 | } |
| 3724 | 3724 | ||
| 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 | } |
| 3740 | 3759 | ||
| 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 { |