| author | |
| committer | |
| log | 73a0b5441be3dc6adb666ca672f3c4f7972cf73e |
| tree | aa88a8e771daaf3ac83aa8909a5d29f444c80299 |
| parent | a31950aa578824e0933b49109f6ac55c84979b6d |
| signature |
Uses a new `float_op_result_ty` ZIR instruction tag.7 files changed, 109 insertions(+), 26 deletions(-)
lib/std/zig/AstGen.zig+34-13| ... | @@ -9390,24 +9390,25 @@ fn builtinCall( | ... | @@ -9390,24 +9390,25 @@ fn builtinCall( |
| 9390 | .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .embed_file), | 9390 | .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .embed_file), |
| 9391 | .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .anyerror_type } }, params[0], .error_name), | 9391 | .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .anyerror_type } }, params[0], .error_name), |
| 9392 | .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, params[0], .set_runtime_safety), | 9392 | .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, params[0], .set_runtime_safety), |
| 9393 | .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), | ||
| 9394 | .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), | ||
| 9395 | .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos), | ||
| 9396 | .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan), | ||
| 9397 | .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp), | ||
| 9398 | .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2), | ||
| 9399 | .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), | ||
| 9400 | .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), | ||
| 9401 | .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), | ||
| 9402 | .abs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .abs), | 9393 | .abs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .abs), |
| 9403 | .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), | ||
| 9404 | .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), | ||
| 9405 | .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), | ||
| 9406 | .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round), | ||
| 9407 | .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name), | 9394 | .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name), |
| 9408 | .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name), | 9395 | .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name), |
| 9409 | .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type), | 9396 | .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type), |
| 9410 | 9397 | ||
| 9398 | .sqrt => return floatUnOp(gz, scope, ri, node, params[0], .sqrt), | ||
| 9399 | .sin => return floatUnOp(gz, scope, ri, node, params[0], .sin), | ||
| 9400 | .cos => return floatUnOp(gz, scope, ri, node, params[0], .cos), | ||
| 9401 | .tan => return floatUnOp(gz, scope, ri, node, params[0], .tan), | ||
| 9402 | .exp => return floatUnOp(gz, scope, ri, node, params[0], .exp), | ||
| 9403 | .exp2 => return floatUnOp(gz, scope, ri, node, params[0], .exp2), | ||
| 9404 | .log => return floatUnOp(gz, scope, ri, node, params[0], .log), | ||
| 9405 | .log2 => return floatUnOp(gz, scope, ri, node, params[0], .log2), | ||
| 9406 | .log10 => return floatUnOp(gz, scope, ri, node, params[0], .log10), | ||
| 9407 | .floor => return floatUnOp(gz, scope, ri, node, params[0], .floor), | ||
| 9408 | .ceil => return floatUnOp(gz, scope, ri, node, params[0], .ceil), | ||
| 9409 | .trunc => return floatUnOp(gz, scope, ri, node, params[0], .trunc), | ||
| 9410 | .round => return floatUnOp(gz, scope, ri, node, params[0], .round), | ||
| 9411 | |||
| 9411 | .int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name), | 9412 | .int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name), |
| 9412 | .float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name), | 9413 | .float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name), |
| 9413 | .ptr_from_int => return typeCast(gz, scope, ri, node, params[0], .ptr_from_int, builtin_name), | 9414 | .ptr_from_int => return typeCast(gz, scope, ri, node, params[0], .ptr_from_int, builtin_name), |
| ... | @@ -9860,6 +9861,26 @@ fn simpleUnOp( | ... | @@ -9860,6 +9861,26 @@ fn simpleUnOp( |
| 9860 | return rvalue(gz, ri, result, node); | 9861 | return rvalue(gz, ri, result, node); |
| 9861 | } | 9862 | } |
| 9862 | 9863 | ||
| 9864 | fn floatUnOp( | ||
| 9865 | gz: *GenZir, | ||
| 9866 | scope: *Scope, | ||
| 9867 | ri: ResultInfo, | ||
| 9868 | node: Ast.Node.Index, | ||
| 9869 | operand_node: Ast.Node.Index, | ||
| 9870 | tag: Zir.Inst.Tag, | ||
| 9871 | ) InnerError!Zir.Inst.Ref { | ||
| 9872 | const result_type = try ri.rl.resultType(gz, node); | ||
| 9873 | const operand_ri: ResultInfo.Loc = if (result_type) |rt| .{ | ||
| 9874 | .ty = try gz.addExtendedPayload(.float_op_result_ty, Zir.Inst.UnNode{ | ||
| 9875 | .node = gz.nodeIndexToRelative(node), | ||
| 9876 | .operand = rt, | ||
| 9877 | }), | ||
| 9878 | } else .none; | ||
| 9879 | const operand = try expr(gz, scope, .{ .rl = operand_ri }, operand_node); | ||
| 9880 | const result = try gz.addUnNode(tag, operand, node); | ||
| 9881 | return rvalue(gz, ri, result, node); | ||
| 9882 | } | ||
| 9883 | |||
| 9863 | fn negation( | 9884 | fn negation( |
| 9864 | gz: *GenZir, | 9885 | gz: *GenZir, |
| 9865 | scope: *Scope, | 9886 | scope: *Scope, |
lib/std/zig/AstRlAnnotate.zig+13-13| ... | @@ -889,6 +889,19 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -889,6 +889,19 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 889 | .frame_address => return true, | 889 | .frame_address => return true, |
| 890 | // These builtins take a single argument with a known result type, but do not consume their | 890 | // These builtins take a single argument with a known result type, but do not consume their |
| 891 | // result pointer. | 891 | // result pointer. |
| 892 | .sqrt, | ||
| 893 | .sin, | ||
| 894 | .cos, | ||
| 895 | .tan, | ||
| 896 | .exp, | ||
| 897 | .exp2, | ||
| 898 | .log, | ||
| 899 | .log2, | ||
| 900 | .log10, | ||
| 901 | .floor, | ||
| 902 | .ceil, | ||
| 903 | .trunc, | ||
| 904 | .round, | ||
| 892 | .size_of, | 905 | .size_of, |
| 893 | .bit_size_of, | 906 | .bit_size_of, |
| 894 | .align_of, | 907 | .align_of, |
| ... | @@ -918,20 +931,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -918,20 +931,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 918 | // result pointer. | 931 | // result pointer. |
| 919 | .int_from_ptr, | 932 | .int_from_ptr, |
| 920 | .int_from_enum, | 933 | .int_from_enum, |
| 921 | .sqrt, | ||
| 922 | .sin, | ||
| 923 | .cos, | ||
| 924 | .tan, | ||
| 925 | .exp, | ||
| 926 | .exp2, | ||
| 927 | .log, | ||
| 928 | .log2, | ||
| 929 | .log10, | ||
| 930 | .abs, | 934 | .abs, |
| 931 | .floor, | ||
| 932 | .ceil, | ||
| 933 | .trunc, | ||
| 934 | .round, | ||
| 935 | .tag_name, | 935 | .tag_name, |
| 936 | .type_name, | 936 | .type_name, |
| 937 | .Frame, | 937 | .Frame, |
lib/std/zig/Zir.zig+6| ... | @@ -2111,6 +2111,11 @@ pub const Inst = struct { | ... | @@ -2111,6 +2111,11 @@ pub const Inst = struct { |
| 2111 | /// This instruction is always `noreturn`, however, it is not considered as such by ZIR-level queries. This allows AstGen to assume that | 2111 | /// This instruction is always `noreturn`, however, it is not considered as such by ZIR-level queries. This allows AstGen to assume that |
| 2112 | /// any code may have gone here, avoiding false-positive "unreachable code" errors. | 2112 | /// any code may have gone here, avoiding false-positive "unreachable code" errors. |
| 2113 | astgen_error, | 2113 | astgen_error, |
| 2114 | /// Given a type, strips away any error unions or optionals stacked | ||
| 2115 | /// on top and returns the base type. That base type must be a float. | ||
| 2116 | /// For example: Provided with error{Foo}!?f64, returns f64. | ||
| 2117 | /// `operand` is `operand: Air.Inst.Ref`. | ||
| 2118 | float_op_result_ty, | ||
| 2114 | 2119 | ||
| 2115 | pub const InstData = struct { | 2120 | pub const InstData = struct { |
| 2116 | opcode: Extended, | 2121 | opcode: Extended, |
| ... | @@ -4436,6 +4441,7 @@ fn findTrackableInner( | ... | @@ -4436,6 +4441,7 @@ fn findTrackableInner( |
| 4436 | .tuple_decl, | 4441 | .tuple_decl, |
| 4437 | .dbg_empty_stmt, | 4442 | .dbg_empty_stmt, |
| 4438 | .astgen_error, | 4443 | .astgen_error, |
| 4444 | .float_op_result_ty, | ||
| 4439 | => return, | 4445 | => return, |
| 4440 | 4446 | ||
| 4441 | // `@TypeOf` has a body. | 4447 | // `@TypeOf` has a body. |
src/Air.zig+4| ... | @@ -1154,6 +1154,10 @@ pub const Inst = struct { | ... | @@ -1154,6 +1154,10 @@ pub const Inst = struct { |
| 1154 | pub fn fromValue(v: Value) Ref { | 1154 | pub fn fromValue(v: Value) Ref { |
| 1155 | return .fromIntern(v.toIntern()); | 1155 | return .fromIntern(v.toIntern()); |
| 1156 | } | 1156 | } |
| 1157 | |||
| 1158 | pub fn fromType(t: Type) Ref { | ||
| 1159 | return .fromIntern(t.toIntern()); | ||
| 1160 | } | ||
| 1157 | }; | 1161 | }; |
| 1158 | 1162 | ||
| 1159 | /// All instructions have an 8-byte payload, which is contained within | 1163 | /// All instructions have an 8-byte payload, which is contained within |
src/Sema.zig+23| ... | @@ -1468,6 +1468,7 @@ fn analyzeBodyInner( | ... | @@ -1468,6 +1468,7 @@ fn analyzeBodyInner( |
| 1468 | continue; | 1468 | continue; |
| 1469 | }, | 1469 | }, |
| 1470 | .astgen_error => return error.AnalysisFail, | 1470 | .astgen_error => return error.AnalysisFail, |
| 1471 | .float_op_result_ty => try sema.zirFloatOpResultType(block, extended), | ||
| 1471 | }; | 1472 | }; |
| 1472 | }, | 1473 | }, |
| 1473 | 1474 | ||
| ... | @@ -25922,6 +25923,28 @@ fn zirBranchHint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -25922,6 +25923,28 @@ fn zirBranchHint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 25922 | } | 25923 | } |
| 25923 | } | 25924 | } |
| 25924 | 25925 | ||
| 25926 | fn zirFloatOpResultType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | ||
| 25927 | const pt = sema.pt; | ||
| 25928 | const zcu = pt.zcu; | ||
| 25929 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | ||
| 25930 | const operand_src = block.builtinCallArgSrc(extra.node, 0); | ||
| 25931 | |||
| 25932 | const raw_ty = try sema.resolveTypeOrPoison(block, operand_src, extra.operand) orelse return .generic_poison_type; | ||
| 25933 | const float_ty = raw_ty.optEuBaseType(zcu); | ||
| 25934 | |||
| 25935 | switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) { | ||
| 25936 | .float, .comptime_float => {}, | ||
| 25937 | else => return sema.fail( | ||
| 25938 | block, | ||
| 25939 | operand_src, | ||
| 25940 | "expected vector of floats or float type, found '{f}'", | ||
| 25941 | .{float_ty.fmt(sema.pt)}, | ||
| 25942 | ), | ||
| 25943 | } | ||
| 25944 | |||
| 25945 | return .fromType(float_ty); | ||
| 25946 | } | ||
| 25947 | |||
| 25925 | fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void { | 25948 | fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void { |
| 25926 | if (block.isComptime()) { | 25949 | if (block.isComptime()) { |
| 25927 | const msg, const fail_block = msg: { | 25950 | const msg, const fail_block = msg: { |
src/print_zir.zig+1| ... | @@ -567,6 +567,7 @@ const Writer = struct { | ... | @@ -567,6 +567,7 @@ const Writer = struct { |
| 567 | .work_group_size, | 567 | .work_group_size, |
| 568 | .work_group_id, | 568 | .work_group_id, |
| 569 | .branch_hint, | 569 | .branch_hint, |
| 570 | .float_op_result_ty, | ||
| 570 | => { | 571 | => { |
| 571 | const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 572 | const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 572 | try self.writeInstRef(stream, inst_data.operand); | 573 | try self.writeInstRef(stream, inst_data.operand); |
test/behavior/floatop.zig+28| ... | @@ -1737,3 +1737,31 @@ test "comptime calls are only memoized when float arguments are bit-for-bit equa | ... | @@ -1737,3 +1737,31 @@ test "comptime calls are only memoized when float arguments are bit-for-bit equa |
| 1737 | try comptime testMemoization(); | 1737 | try comptime testMemoization(); |
| 1738 | try comptime testVectorMemoization(@Vector(4, f32)); | 1738 | try comptime testVectorMemoization(@Vector(4, f32)); |
| 1739 | } | 1739 | } |
| 1740 | |||
| 1741 | test "result location forwarded through unary float builtins" { | ||
| 1742 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1743 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1744 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1745 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | ||
| 1746 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1747 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 1748 | |||
| 1749 | const S = struct { | ||
| 1750 | var x: u32 = 10; | ||
| 1751 | }; | ||
| 1752 | |||
| 1753 | var y: f64 = 0.0; | ||
| 1754 | y = @sqrt(@floatFromInt(S.x)); | ||
| 1755 | y = @sin(@floatFromInt(S.x)); | ||
| 1756 | y = @cos(@floatFromInt(S.x)); | ||
| 1757 | y = @tan(@floatFromInt(S.x)); | ||
| 1758 | y = @exp(@floatFromInt(S.x)); | ||
| 1759 | y = @exp2(@floatFromInt(S.x)); | ||
| 1760 | y = @log(@floatFromInt(S.x)); | ||
| 1761 | y = @log2(@floatFromInt(S.x)); | ||
| 1762 | y = @log10(@floatFromInt(S.x)); | ||
| 1763 | y = @floor(@floatFromInt(S.x)); | ||
| 1764 | y = @ceil(@floatFromInt(S.x)); | ||
| 1765 | y = @trunc(@floatFromInt(S.x)); | ||
| 1766 | y = @round(@floatFromInt(S.x)); | ||
| 1767 | } |