| author | |
| committer | |
| log | 09f1d62bdfb5794534b21d1cd9dafc4822697d60 |
| tree | 437f6c19a6f0f16ef29fb91513176bb8aa0c91f0 |
| parent | c4eaff6665132287d05272bef8890e4607ff017c |
The reason for having `@tan` is that we already have `@sin` and `@cos`
because some targets have machine code instructions for them, but in the
case that the implementation needs to go into compiler-rt, sin, cos, and
tan all share a common dependency which includes a table of data. To
avoid duplicating this table of data, we promote tan to become a builtin
alongside sin and cos.
ZIR: The tag enum is at capacity so this commit moves
`field_call_bind_named` to be `extended`. I measured this as one of
the least used tags in the zig codebase.
Fix libc math suffix for `f32` being wrong in both stage1 and stage2.
stage1: add missing libc prefix for float functions.25 files changed, 203 insertions(+), 69 deletions(-)
doc/langref.html.in+15-1| ... | @@ -8026,7 +8026,7 @@ fn func(y: *i32) void { | ... | @@ -8026,7 +8026,7 @@ fn func(y: *i32) void { |
| 8026 | only rounds once, and is thus more accurate. | 8026 | only rounds once, and is thus more accurate. |
| 8027 | </p> | 8027 | </p> |
| 8028 | <p> | 8028 | <p> |
| 8029 | Supports Floats and Vectors of floats. | 8029 | Supports {#link|Floats#} and {#link|Vectors#} of floats. |
| 8030 | </p> | 8030 | </p> |
| 8031 | {#header_close#} | 8031 | {#header_close#} |
| 8032 | 8032 | ||
| ... | @@ -9440,6 +9440,7 @@ fn doTheTest() !void { | ... | @@ -9440,6 +9440,7 @@ fn doTheTest() !void { |
| 9440 | <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>. | 9440 | <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>. |
| 9441 | </p> | 9441 | </p> |
| 9442 | {#header_close#} | 9442 | {#header_close#} |
| 9443 | |||
| 9443 | {#header_open|@cos#} | 9444 | {#header_open|@cos#} |
| 9444 | <pre>{#syntax#}@cos(value: anytype) @TypeOf(value){#endsyntax#}</pre> | 9445 | <pre>{#syntax#}@cos(value: anytype) @TypeOf(value){#endsyntax#}</pre> |
| 9445 | <p> | 9446 | <p> |
| ... | @@ -9451,6 +9452,19 @@ fn doTheTest() !void { | ... | @@ -9451,6 +9452,19 @@ fn doTheTest() !void { |
| 9451 | <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>. | 9452 | <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>. |
| 9452 | </p> | 9453 | </p> |
| 9453 | {#header_close#} | 9454 | {#header_close#} |
| 9455 | |||
| 9456 | {#header_open|@tan#} | ||
| 9457 | <pre>{#syntax#}@tan(value: anytype) @TypeOf(value){#endsyntax#}</pre> | ||
| 9458 | <p> | ||
| 9459 | Tangent trigonometric function on a floating point number. | ||
| 9460 | Uses a dedicated hardware instruction when available. | ||
| 9461 | </p> | ||
| 9462 | <p> | ||
| 9463 | Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that | ||
| 9464 | <a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>. | ||
| 9465 | </p> | ||
| 9466 | {#header_close#} | ||
| 9467 | |||
| 9454 | {#header_open|@exp#} | 9468 | {#header_open|@exp#} |
| 9455 | <pre>{#syntax#}@exp(value: anytype) @TypeOf(value){#endsyntax#}</pre> | 9469 | <pre>{#syntax#}@exp(value: anytype) @TypeOf(value){#endsyntax#}</pre> |
| 9456 | <p> | 9470 | <p> |
lib/std/math/complex/tanh.zig+2-2| ... | @@ -49,7 +49,7 @@ fn tanh32(z: Complex(f32)) Complex(f32) { | ... | @@ -49,7 +49,7 @@ fn tanh32(z: Complex(f32)) Complex(f32) { |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | // Kahan's algorithm | 51 | // Kahan's algorithm |
| 52 | const t = math.tan(y); | 52 | const t = @tan(y); |
| 53 | const beta = 1.0 + t * t; | 53 | const beta = 1.0 + t * t; |
| 54 | const s = math.sinh(x); | 54 | const s = math.sinh(x); |
| 55 | const rho = @sqrt(1 + s * s); | 55 | const rho = @sqrt(1 + s * s); |
| ... | @@ -92,7 +92,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) { | ... | @@ -92,7 +92,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) { |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | // Kahan's algorithm | 94 | // Kahan's algorithm |
| 95 | const t = math.tan(y); | 95 | const t = @tan(y); |
| 96 | const beta = 1.0 + t * t; | 96 | const beta = 1.0 + t * t; |
| 97 | const s = math.sinh(x); | 97 | const s = math.sinh(x); |
| 98 | const rho = @sqrt(1 + s * s); | 98 | const rho = @sqrt(1 + s * s); |
src/Air.zig+6-2| ... | @@ -249,12 +249,15 @@ pub const Inst = struct { | ... | @@ -249,12 +249,15 @@ pub const Inst = struct { |
| 249 | /// Square root of a floating point number. | 249 | /// Square root of a floating point number. |
| 250 | /// Uses the `un_op` field. | 250 | /// Uses the `un_op` field. |
| 251 | sqrt, | 251 | sqrt, |
| 252 | /// Sine a floating point number. | 252 | /// Sine function on a floating point number. |
| 253 | /// Uses the `un_op` field. | 253 | /// Uses the `un_op` field. |
| 254 | sin, | 254 | sin, |
| 255 | /// Cosine a floating point number. | 255 | /// Cosine function on a floating point number. |
| 256 | /// Uses the `un_op` field. | 256 | /// Uses the `un_op` field. |
| 257 | cos, | 257 | cos, |
| 258 | /// Tangent function on a floating point number. | ||
| 259 | /// Uses the `un_op` field. | ||
| 260 | tan, | ||
| 258 | /// Base e exponential of a floating point number. | 261 | /// Base e exponential of a floating point number. |
| 259 | /// Uses the `un_op` field. | 262 | /// Uses the `un_op` field. |
| 260 | exp, | 263 | exp, |
| ... | @@ -921,6 +924,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -921,6 +924,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 921 | .sqrt, | 924 | .sqrt, |
| 922 | .sin, | 925 | .sin, |
| 923 | .cos, | 926 | .cos, |
| 927 | .tan, | ||
| 924 | .exp, | 928 | .exp, |
| 925 | .exp2, | 929 | .exp2, |
| 926 | .log, | 930 | .log, |
src/AstGen.zig+4-2| ... | @@ -2237,7 +2237,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2237,7 +2237,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2237 | .field_call_bind, | 2237 | .field_call_bind, |
| 2238 | .field_ptr_named, | 2238 | .field_ptr_named, |
| 2239 | .field_val_named, | 2239 | .field_val_named, |
| 2240 | .field_call_bind_named, | ||
| 2241 | .func, | 2240 | .func, |
| 2242 | .func_inferred, | 2241 | .func_inferred, |
| 2243 | .int, | 2242 | .int, |
| ... | @@ -2329,6 +2328,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2329,6 +2328,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2329 | .sqrt, | 2328 | .sqrt, |
| 2330 | .sin, | 2329 | .sin, |
| 2331 | .cos, | 2330 | .cos, |
| 2331 | .tan, | ||
| 2332 | .exp, | 2332 | .exp, |
| 2333 | .exp2, | 2333 | .exp2, |
| 2334 | .log, | 2334 | .log, |
| ... | @@ -7259,6 +7259,7 @@ fn builtinCall( | ... | @@ -7259,6 +7259,7 @@ fn builtinCall( |
| 7259 | .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt), | 7259 | .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt), |
| 7260 | .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin), | 7260 | .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin), |
| 7261 | .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos), | 7261 | .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos), |
| 7262 | .tan => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tan), | ||
| 7262 | .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp), | 7263 | .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp), |
| 7263 | .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2), | 7264 | .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2), |
| 7264 | .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log), | 7265 | .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log), |
| ... | @@ -7947,7 +7948,8 @@ fn calleeExpr( | ... | @@ -7947,7 +7948,8 @@ fn calleeExpr( |
| 7947 | if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) { | 7948 | if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) { |
| 7948 | const lhs = try expr(gz, scope, .ref, params[0]); | 7949 | const lhs = try expr(gz, scope, .ref, params[0]); |
| 7949 | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); | 7950 | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); |
| 7950 | return gz.addPlNode(.field_call_bind_named, node, Zir.Inst.FieldNamed{ | 7951 | return gz.addExtendedPayload(.field_call_bind_named, Zir.Inst.FieldNamedNode{ |
| 7952 | .node = gz.nodeIndexToRelative(node), | ||
| 7951 | .lhs = lhs, | 7953 | .lhs = lhs, |
| 7952 | .field_name = field_name, | 7954 | .field_name = field_name, |
| 7953 | }); | 7955 | }); |
src/BuiltinFn.zig+8| ... | @@ -89,6 +89,7 @@ pub const Tag = enum { | ... | @@ -89,6 +89,7 @@ pub const Tag = enum { |
| 89 | sqrt, | 89 | sqrt, |
| 90 | sin, | 90 | sin, |
| 91 | cos, | 91 | cos, |
| 92 | tan, | ||
| 92 | exp, | 93 | exp, |
| 93 | exp2, | 94 | exp2, |
| 94 | log, | 95 | log, |
| ... | @@ -771,6 +772,13 @@ pub const list = list: { | ... | @@ -771,6 +772,13 @@ pub const list = list: { |
| 771 | .param_count = 1, | 772 | .param_count = 1, |
| 772 | }, | 773 | }, |
| 773 | }, | 774 | }, |
| 775 | .{ | ||
| 776 | "@tan", | ||
| 777 | .{ | ||
| 778 | .tag = .tan, | ||
| 779 | .param_count = 1, | ||
| 780 | }, | ||
| 781 | }, | ||
| 774 | .{ | 782 | .{ |
| 775 | "@exp", | 783 | "@exp", |
| 776 | .{ | 784 | .{ |
src/Liveness.zig+1| ... | @@ -422,6 +422,7 @@ fn analyzeInst( | ... | @@ -422,6 +422,7 @@ fn analyzeInst( |
| 422 | .sqrt, | 422 | .sqrt, |
| 423 | .sin, | 423 | .sin, |
| 424 | .cos, | 424 | .cos, |
| 425 | .tan, | ||
| 425 | .exp, | 426 | .exp, |
| 426 | .exp2, | 427 | .exp2, |
| 427 | .log, | 428 | .log, |
src/Sema.zig+35-35| ... | @@ -743,7 +743,6 @@ fn analyzeBodyInner( | ... | @@ -743,7 +743,6 @@ fn analyzeBodyInner( |
| 743 | .field_val => try sema.zirFieldVal(block, inst), | 743 | .field_val => try sema.zirFieldVal(block, inst), |
| 744 | .field_val_named => try sema.zirFieldValNamed(block, inst), | 744 | .field_val_named => try sema.zirFieldValNamed(block, inst), |
| 745 | .field_call_bind => try sema.zirFieldCallBind(block, inst), | 745 | .field_call_bind => try sema.zirFieldCallBind(block, inst), |
| 746 | .field_call_bind_named => try sema.zirFieldCallBindNamed(block, inst), | ||
| 747 | .func => try sema.zirFunc(block, inst, false), | 746 | .func => try sema.zirFunc(block, inst, false), |
| 748 | .func_inferred => try sema.zirFunc(block, inst, true), | 747 | .func_inferred => try sema.zirFunc(block, inst, true), |
| 749 | .import => try sema.zirImport(block, inst), | 748 | .import => try sema.zirImport(block, inst), |
| ... | @@ -855,6 +854,7 @@ fn analyzeBodyInner( | ... | @@ -855,6 +854,7 @@ fn analyzeBodyInner( |
| 855 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), | 854 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), |
| 856 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), | 855 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), |
| 857 | .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos), | 856 | .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos), |
| 857 | .tan => try sema.zirUnaryMath(block, inst, .tan, Value.tan), | ||
| 858 | .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp), | 858 | .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp), |
| 859 | .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2), | 859 | .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2), |
| 860 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), | 860 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), |
| ... | @@ -910,35 +910,36 @@ fn analyzeBodyInner( | ... | @@ -910,35 +910,36 @@ fn analyzeBodyInner( |
| 910 | const extended = datas[inst].extended; | 910 | const extended = datas[inst].extended; |
| 911 | break :ext switch (extended.opcode) { | 911 | break :ext switch (extended.opcode) { |
| 912 | // zig fmt: off | 912 | // zig fmt: off |
| 913 | .func => try sema.zirFuncExtended( block, extended, inst), | 913 | .func => try sema.zirFuncExtended( block, extended, inst), |
| 914 | .variable => try sema.zirVarExtended( block, extended), | 914 | .variable => try sema.zirVarExtended( block, extended), |
| 915 | .struct_decl => try sema.zirStructDecl( block, extended, inst), | 915 | .struct_decl => try sema.zirStructDecl( block, extended, inst), |
| 916 | .enum_decl => try sema.zirEnumDecl( block, extended), | 916 | .enum_decl => try sema.zirEnumDecl( block, extended), |
| 917 | .union_decl => try sema.zirUnionDecl( block, extended, inst), | 917 | .union_decl => try sema.zirUnionDecl( block, extended, inst), |
| 918 | .opaque_decl => try sema.zirOpaqueDecl( block, extended), | 918 | .opaque_decl => try sema.zirOpaqueDecl( block, extended), |
| 919 | .ret_ptr => try sema.zirRetPtr( block, extended), | 919 | .ret_ptr => try sema.zirRetPtr( block, extended), |
| 920 | .ret_type => try sema.zirRetType( block, extended), | 920 | .ret_type => try sema.zirRetType( block, extended), |
| 921 | .this => try sema.zirThis( block, extended), | 921 | .this => try sema.zirThis( block, extended), |
| 922 | .ret_addr => try sema.zirRetAddr( block, extended), | 922 | .ret_addr => try sema.zirRetAddr( block, extended), |
| 923 | .builtin_src => try sema.zirBuiltinSrc( block, extended), | 923 | .builtin_src => try sema.zirBuiltinSrc( block, extended), |
| 924 | .error_return_trace => try sema.zirErrorReturnTrace( block, extended), | 924 | .error_return_trace => try sema.zirErrorReturnTrace( block, extended), |
| 925 | .frame => try sema.zirFrame( block, extended), | 925 | .frame => try sema.zirFrame( block, extended), |
| 926 | .frame_address => try sema.zirFrameAddress( block, extended), | 926 | .frame_address => try sema.zirFrameAddress( block, extended), |
| 927 | .alloc => try sema.zirAllocExtended( block, extended), | 927 | .alloc => try sema.zirAllocExtended( block, extended), |
| 928 | .builtin_extern => try sema.zirBuiltinExtern( block, extended), | 928 | .builtin_extern => try sema.zirBuiltinExtern( block, extended), |
| 929 | .@"asm" => try sema.zirAsm( block, extended), | 929 | .@"asm" => try sema.zirAsm( block, extended), |
| 930 | .typeof_peer => try sema.zirTypeofPeer( block, extended), | 930 | .typeof_peer => try sema.zirTypeofPeer( block, extended), |
| 931 | .compile_log => try sema.zirCompileLog( block, extended), | 931 | .compile_log => try sema.zirCompileLog( block, extended), |
| 932 | .add_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), | 932 | .add_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), |
| 933 | .sub_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), | 933 | .sub_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), |
| 934 | .mul_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), | 934 | .mul_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), |
| 935 | .shl_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), | 935 | .shl_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), |
| 936 | .c_undef => try sema.zirCUndef( block, extended), | 936 | .c_undef => try sema.zirCUndef( block, extended), |
| 937 | .c_include => try sema.zirCInclude( block, extended), | 937 | .c_include => try sema.zirCInclude( block, extended), |
| 938 | .c_define => try sema.zirCDefine( block, extended), | 938 | .c_define => try sema.zirCDefine( block, extended), |
| 939 | .wasm_memory_size => try sema.zirWasmMemorySize( block, extended), | 939 | .wasm_memory_size => try sema.zirWasmMemorySize( block, extended), |
| 940 | .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), | 940 | .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), |
| 941 | .prefetch => try sema.zirPrefetch( block, extended), | 941 | .prefetch => try sema.zirPrefetch( block, extended), |
| 942 | .field_call_bind_named => try sema.zirFieldCallBindNamed(block, extended), | ||
| 942 | // zig fmt: on | 943 | // zig fmt: on |
| 943 | .dbg_block_begin => { | 944 | .dbg_block_begin => { |
| 944 | dbg_block_begins += 1; | 945 | dbg_block_begins += 1; |
| ... | @@ -6938,14 +6939,13 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -6938,14 +6939,13 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 6938 | return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src); | 6939 | return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src); |
| 6939 | } | 6940 | } |
| 6940 | 6941 | ||
| 6941 | fn zirFieldCallBindNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6942 | fn zirFieldCallBindNamed(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 6942 | const tracy = trace(@src()); | 6943 | const tracy = trace(@src()); |
| 6943 | defer tracy.end(); | 6944 | defer tracy.end(); |
| 6944 | 6945 | ||
| 6945 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 6946 | const extra = sema.code.extraData(Zir.Inst.FieldNamedNode, extended.operand).data; |
| 6946 | const src = inst_data.src(); | 6947 | const src: LazySrcLoc = .{ .node_offset = extra.node }; |
| 6947 | const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 6948 | const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 6948 | const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; | ||
| 6949 | const object_ptr = sema.resolveInst(extra.lhs); | 6949 | const object_ptr = sema.resolveInst(extra.lhs); |
| 6950 | const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name); | 6950 | const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name); |
| 6951 | return sema.fieldCallBind(block, src, object_ptr, field_name, field_name_src); | 6951 | return sema.fieldCallBind(block, src, object_ptr, field_name, field_name_src); |
src/Zir.zig+21-12| ... | @@ -407,15 +407,6 @@ pub const Inst = struct { | ... | @@ -407,15 +407,6 @@ pub const Inst = struct { |
| 407 | /// The field name is a comptime instruction. Used by @field. | 407 | /// The field name is a comptime instruction. Used by @field. |
| 408 | /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed. | 408 | /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed. |
| 409 | field_val_named, | 409 | field_val_named, |
| 410 | /// Given a pointer to a struct or object that contains virtual fields, returns the | ||
| 411 | /// named field. If there is no named field, searches in the type for a decl that | ||
| 412 | /// matches the field name. The decl is resolved and we ensure that it's a function | ||
| 413 | /// which can accept the object as the first parameter, with one pointer fixup. If | ||
| 414 | /// all of that works, this instruction produces a special "bound function" value | ||
| 415 | /// which contains both the function and the saved first parameter value. | ||
| 416 | /// Bound functions may only be used as the function parameter to a `call` or | ||
| 417 | /// `builtin_call` instruction. Any other use is invalid zir and may crash the compiler. | ||
| 418 | field_call_bind_named, | ||
| 419 | /// Returns a function type, or a function instance, depending on whether | 410 | /// Returns a function type, or a function instance, depending on whether |
| 420 | /// the body_len is 0. Calling convention is auto. | 411 | /// the body_len is 0. Calling convention is auto. |
| 421 | /// Uses the `pl_node` union field. `payload_index` points to a `Func`. | 412 | /// Uses the `pl_node` union field. `payload_index` points to a `Func`. |
| ... | @@ -797,6 +788,8 @@ pub const Inst = struct { | ... | @@ -797,6 +788,8 @@ pub const Inst = struct { |
| 797 | sin, | 788 | sin, |
| 798 | /// Implement builtin `@cos`. Uses `un_node`. | 789 | /// Implement builtin `@cos`. Uses `un_node`. |
| 799 | cos, | 790 | cos, |
| 791 | /// Implement builtin `@tan`. Uses `un_node`. | ||
| 792 | tan, | ||
| 800 | /// Implement builtin `@exp`. Uses `un_node`. | 793 | /// Implement builtin `@exp`. Uses `un_node`. |
| 801 | exp, | 794 | exp, |
| 802 | /// Implement builtin `@exp2`. Uses `un_node`. | 795 | /// Implement builtin `@exp2`. Uses `un_node`. |
| ... | @@ -1069,7 +1062,6 @@ pub const Inst = struct { | ... | @@ -1069,7 +1062,6 @@ pub const Inst = struct { |
| 1069 | .field_call_bind, | 1062 | .field_call_bind, |
| 1070 | .field_ptr_named, | 1063 | .field_ptr_named, |
| 1071 | .field_val_named, | 1064 | .field_val_named, |
| 1072 | .field_call_bind_named, | ||
| 1073 | .func, | 1065 | .func, |
| 1074 | .func_inferred, | 1066 | .func_inferred, |
| 1075 | .has_decl, | 1067 | .has_decl, |
| ... | @@ -1179,6 +1171,7 @@ pub const Inst = struct { | ... | @@ -1179,6 +1171,7 @@ pub const Inst = struct { |
| 1179 | .sqrt, | 1171 | .sqrt, |
| 1180 | .sin, | 1172 | .sin, |
| 1181 | .cos, | 1173 | .cos, |
| 1174 | .tan, | ||
| 1182 | .exp, | 1175 | .exp, |
| 1183 | .exp2, | 1176 | .exp2, |
| 1184 | .log, | 1177 | .log, |
| ... | @@ -1358,7 +1351,6 @@ pub const Inst = struct { | ... | @@ -1358,7 +1351,6 @@ pub const Inst = struct { |
| 1358 | .field_call_bind, | 1351 | .field_call_bind, |
| 1359 | .field_ptr_named, | 1352 | .field_ptr_named, |
| 1360 | .field_val_named, | 1353 | .field_val_named, |
| 1361 | .field_call_bind_named, | ||
| 1362 | .func, | 1354 | .func, |
| 1363 | .func_inferred, | 1355 | .func_inferred, |
| 1364 | .has_decl, | 1356 | .has_decl, |
| ... | @@ -1451,6 +1443,7 @@ pub const Inst = struct { | ... | @@ -1451,6 +1443,7 @@ pub const Inst = struct { |
| 1451 | .sqrt, | 1443 | .sqrt, |
| 1452 | .sin, | 1444 | .sin, |
| 1453 | .cos, | 1445 | .cos, |
| 1446 | .tan, | ||
| 1454 | .exp, | 1447 | .exp, |
| 1455 | .exp2, | 1448 | .exp2, |
| 1456 | .log, | 1449 | .log, |
| ... | @@ -1607,7 +1600,6 @@ pub const Inst = struct { | ... | @@ -1607,7 +1600,6 @@ pub const Inst = struct { |
| 1607 | .field_ptr_named = .pl_node, | 1600 | .field_ptr_named = .pl_node, |
| 1608 | .field_val_named = .pl_node, | 1601 | .field_val_named = .pl_node, |
| 1609 | .field_call_bind = .pl_node, | 1602 | .field_call_bind = .pl_node, |
| 1610 | .field_call_bind_named = .pl_node, | ||
| 1611 | .func = .pl_node, | 1603 | .func = .pl_node, |
| 1612 | .func_inferred = .pl_node, | 1604 | .func_inferred = .pl_node, |
| 1613 | .import = .str_tok, | 1605 | .import = .str_tok, |
| ... | @@ -1713,6 +1705,7 @@ pub const Inst = struct { | ... | @@ -1713,6 +1705,7 @@ pub const Inst = struct { |
| 1713 | .sqrt = .un_node, | 1705 | .sqrt = .un_node, |
| 1714 | .sin = .un_node, | 1706 | .sin = .un_node, |
| 1715 | .cos = .un_node, | 1707 | .cos = .un_node, |
| 1708 | .tan = .un_node, | ||
| 1716 | .exp = .un_node, | 1709 | .exp = .un_node, |
| 1717 | .exp2 = .un_node, | 1710 | .exp2 = .un_node, |
| 1718 | .log = .un_node, | 1711 | .log = .un_node, |
| ... | @@ -1928,6 +1921,16 @@ pub const Inst = struct { | ... | @@ -1928,6 +1921,16 @@ pub const Inst = struct { |
| 1928 | dbg_block_begin, | 1921 | dbg_block_begin, |
| 1929 | /// Marks the end of a semantic scope for debug info variables. | 1922 | /// Marks the end of a semantic scope for debug info variables. |
| 1930 | dbg_block_end, | 1923 | dbg_block_end, |
| 1924 | /// Given a pointer to a struct or object that contains virtual fields, returns the | ||
| 1925 | /// named field. If there is no named field, searches in the type for a decl that | ||
| 1926 | /// matches the field name. The decl is resolved and we ensure that it's a function | ||
| 1927 | /// which can accept the object as the first parameter, with one pointer fixup. If | ||
| 1928 | /// all of that works, this instruction produces a special "bound function" value | ||
| 1929 | /// which contains both the function and the saved first parameter value. | ||
| 1930 | /// Bound functions may only be used as the function parameter to a `call` or | ||
| 1931 | /// `builtin_call` instruction. Any other use is invalid zir and may crash the compiler. | ||
| 1932 | /// Uses `pl_node` field. The AST node is the `@field` builtin. Payload is FieldNamedNode. | ||
| 1933 | field_call_bind_named, | ||
| 1931 | 1934 | ||
| 1932 | pub const InstData = struct { | 1935 | pub const InstData = struct { |
| 1933 | opcode: Extended, | 1936 | opcode: Extended, |
| ... | @@ -2963,6 +2966,12 @@ pub const Inst = struct { | ... | @@ -2963,6 +2966,12 @@ pub const Inst = struct { |
| 2963 | field_name: Ref, | 2966 | field_name: Ref, |
| 2964 | }; | 2967 | }; |
| 2965 | 2968 | ||
| 2969 | pub const FieldNamedNode = struct { | ||
| 2970 | node: i32, | ||
| 2971 | lhs: Ref, | ||
| 2972 | field_name: Ref, | ||
| 2973 | }; | ||
| 2974 | |||
| 2966 | pub const As = struct { | 2975 | pub const As = struct { |
| 2967 | dest_type: Ref, | 2976 | dest_type: Ref, |
| 2968 | operand: Ref, | 2977 | operand: Ref, |
src/arch/aarch64/CodeGen.zig+1| ... | @@ -533,6 +533,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -533,6 +533,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 533 | .sqrt, | 533 | .sqrt, |
| 534 | .sin, | 534 | .sin, |
| 535 | .cos, | 535 | .cos, |
| 536 | .tan, | ||
| 536 | .exp, | 537 | .exp, |
| 537 | .exp2, | 538 | .exp2, |
| 538 | .log, | 539 | .log, |
src/arch/arm/CodeGen.zig+1| ... | @@ -571,6 +571,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -571,6 +571,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 571 | .sqrt, | 571 | .sqrt, |
| 572 | .sin, | 572 | .sin, |
| 573 | .cos, | 573 | .cos, |
| 574 | .tan, | ||
| 574 | .exp, | 575 | .exp, |
| 575 | .exp2, | 576 | .exp2, |
| 576 | .log, | 577 | .log, |
src/arch/riscv64/CodeGen.zig+1| ... | @@ -500,6 +500,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -500,6 +500,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 500 | .sqrt, | 500 | .sqrt, |
| 501 | .sin, | 501 | .sin, |
| 502 | .cos, | 502 | .cos, |
| 503 | .tan, | ||
| 503 | .exp, | 504 | .exp, |
| 504 | .exp2, | 505 | .exp2, |
| 505 | .log, | 506 | .log, |
src/arch/sparcv9/CodeGen.zig+1| ... | @@ -451,6 +451,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -451,6 +451,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 451 | .sqrt, | 451 | .sqrt, |
| 452 | .sin, | 452 | .sin, |
| 453 | .cos, | 453 | .cos, |
| 454 | .tan, | ||
| 454 | .exp, | 455 | .exp, |
| 455 | .exp2, | 456 | .exp2, |
| 456 | .log, | 457 | .log, |
src/arch/wasm/CodeGen.zig+1| ... | @@ -1559,6 +1559,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1559,6 +1559,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1559 | .sqrt, | 1559 | .sqrt, |
| 1560 | .sin, | 1560 | .sin, |
| 1561 | .cos, | 1561 | .cos, |
| 1562 | .tan, | ||
| 1562 | .exp, | 1563 | .exp, |
| 1563 | .exp2, | 1564 | .exp2, |
| 1564 | .log, | 1565 | .log, |
src/arch/x86_64/CodeGen.zig+1| ... | @@ -656,6 +656,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -656,6 +656,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 656 | .sqrt, | 656 | .sqrt, |
| 657 | .sin, | 657 | .sin, |
| 658 | .cos, | 658 | .cos, |
| 659 | .tan, | ||
| 659 | .exp, | 660 | .exp, |
| 660 | .exp2, | 661 | .exp2, |
| 661 | .log, | 662 | .log, |
src/codegen/c.zig+1| ... | @@ -1749,6 +1749,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1749,6 +1749,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1749 | .sqrt, | 1749 | .sqrt, |
| 1750 | .sin, | 1750 | .sin, |
| 1751 | .cos, | 1751 | .cos, |
| 1752 | .tan, | ||
| 1752 | .exp, | 1753 | .exp, |
| 1753 | .exp2, | 1754 | .exp2, |
| 1754 | .log, | 1755 | .log, |
src/codegen/llvm.zig+5-2| ... | @@ -3521,6 +3521,7 @@ pub const FuncGen = struct { | ... | @@ -3521,6 +3521,7 @@ pub const FuncGen = struct { |
| 3521 | .sqrt => try self.airUnaryOp(inst, .sqrt), | 3521 | .sqrt => try self.airUnaryOp(inst, .sqrt), |
| 3522 | .sin => try self.airUnaryOp(inst, .sin), | 3522 | .sin => try self.airUnaryOp(inst, .sin), |
| 3523 | .cos => try self.airUnaryOp(inst, .cos), | 3523 | .cos => try self.airUnaryOp(inst, .cos), |
| 3524 | .tan => try self.airUnaryOp(inst, .tan), | ||
| 3524 | .exp => try self.airUnaryOp(inst, .exp), | 3525 | .exp => try self.airUnaryOp(inst, .exp), |
| 3525 | .exp2 => try self.airUnaryOp(inst, .exp2), | 3526 | .exp2 => try self.airUnaryOp(inst, .exp2), |
| 3526 | .log => try self.airUnaryOp(inst, .log), | 3527 | .log => try self.airUnaryOp(inst, .log), |
| ... | @@ -5553,7 +5554,7 @@ pub const FuncGen = struct { | ... | @@ -5553,7 +5554,7 @@ pub const FuncGen = struct { |
| 5553 | fn libcFloatSuffix(float_bits: u16) []const u8 { | 5554 | fn libcFloatSuffix(float_bits: u16) []const u8 { |
| 5554 | return switch (float_bits) { | 5555 | return switch (float_bits) { |
| 5555 | 16 => "h", // Non-standard | 5556 | 16 => "h", // Non-standard |
| 5556 | 32 => "s", | 5557 | 32 => "f", |
| 5557 | 64 => "", | 5558 | 64 => "", |
| 5558 | 80 => "x", // Non-standard | 5559 | 80 => "x", // Non-standard |
| 5559 | 128 => "q", // Non-standard (mimics convention in GCC libquadmath) | 5560 | 128 => "q", // Non-standard (mimics convention in GCC libquadmath) |
| ... | @@ -5661,6 +5662,7 @@ pub const FuncGen = struct { | ... | @@ -5661,6 +5662,7 @@ pub const FuncGen = struct { |
| 5661 | sin, | 5662 | sin, |
| 5662 | sqrt, | 5663 | sqrt, |
| 5663 | sub, | 5664 | sub, |
| 5665 | tan, | ||
| 5664 | trunc, | 5666 | trunc, |
| 5665 | }; | 5667 | }; |
| 5666 | 5668 | ||
| ... | @@ -5684,7 +5686,7 @@ pub const FuncGen = struct { | ... | @@ -5684,7 +5686,7 @@ pub const FuncGen = struct { |
| 5684 | const llvm_ty = try self.dg.llvmType(ty); | 5686 | const llvm_ty = try self.dg.llvmType(ty); |
| 5685 | const scalar_llvm_ty = try self.dg.llvmType(scalar_ty); | 5687 | const scalar_llvm_ty = try self.dg.llvmType(scalar_ty); |
| 5686 | 5688 | ||
| 5687 | const intrinsics_allowed = intrinsicsAllowed(scalar_ty, target); | 5689 | const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target); |
| 5688 | var fn_name_buf: [64]u8 = undefined; | 5690 | var fn_name_buf: [64]u8 = undefined; |
| 5689 | const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { | 5691 | const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { |
| 5690 | // Some operations are dedicated LLVM instructions, not available as intrinsics | 5692 | // Some operations are dedicated LLVM instructions, not available as intrinsics |
| ... | @@ -5720,6 +5722,7 @@ pub const FuncGen = struct { | ... | @@ -5720,6 +5722,7 @@ pub const FuncGen = struct { |
| 5720 | .round, | 5722 | .round, |
| 5721 | .sin, | 5723 | .sin, |
| 5722 | .sqrt, | 5724 | .sqrt, |
| 5725 | .tan, | ||
| 5723 | .trunc, | 5726 | .trunc, |
| 5724 | => FloatOpStrat{ | 5727 | => FloatOpStrat{ |
| 5725 | .libc = std.fmt.bufPrintZ(&fn_name_buf, "{s}{s}{s}", .{ | 5728 | .libc = std.fmt.bufPrintZ(&fn_name_buf, "{s}{s}{s}", .{ |
src/print_air.zig+1| ... | @@ -158,6 +158,7 @@ const Writer = struct { | ... | @@ -158,6 +158,7 @@ const Writer = struct { |
| 158 | .sqrt, | 158 | .sqrt, |
| 159 | .sin, | 159 | .sin, |
| 160 | .cos, | 160 | .cos, |
| 161 | .tan, | ||
| 161 | .exp, | 162 | .exp, |
| 162 | .exp2, | 163 | .exp2, |
| 163 | .log, | 164 | .log, |
src/print_zir.zig+11-1| ... | @@ -207,6 +207,7 @@ const Writer = struct { | ... | @@ -207,6 +207,7 @@ const Writer = struct { |
| 207 | .sqrt, | 207 | .sqrt, |
| 208 | .sin, | 208 | .sin, |
| 209 | .cos, | 209 | .cos, |
| 210 | .tan, | ||
| 210 | .exp, | 211 | .exp, |
| 211 | .exp2, | 212 | .exp2, |
| 212 | .log, | 213 | .log, |
| ... | @@ -400,7 +401,6 @@ const Writer = struct { | ... | @@ -400,7 +401,6 @@ const Writer = struct { |
| 400 | 401 | ||
| 401 | .field_ptr_named, | 402 | .field_ptr_named, |
| 402 | .field_val_named, | 403 | .field_val_named, |
| 403 | .field_call_bind_named, | ||
| 404 | => try self.writePlNodeFieldNamed(stream, inst), | 404 | => try self.writePlNodeFieldNamed(stream, inst), |
| 405 | 405 | ||
| 406 | .as_node => try self.writeAs(stream, inst), | 406 | .as_node => try self.writeAs(stream, inst), |
| ... | @@ -509,6 +509,16 @@ const Writer = struct { | ... | @@ -509,6 +509,16 @@ const Writer = struct { |
| 509 | try stream.writeAll(")) "); | 509 | try stream.writeAll(")) "); |
| 510 | try self.writeSrc(stream, src); | 510 | try self.writeSrc(stream, src); |
| 511 | }, | 511 | }, |
| 512 | |||
| 513 | .field_call_bind_named => { | ||
| 514 | const extra = self.code.extraData(Zir.Inst.FieldNamedNode, extended.operand).data; | ||
| 515 | const src: LazySrcLoc = .{ .node_offset = extra.node }; | ||
| 516 | try self.writeInstRef(stream, extra.lhs); | ||
| 517 | try stream.writeAll(", "); | ||
| 518 | try self.writeInstRef(stream, extra.field_name); | ||
| 519 | try stream.writeAll(") "); | ||
| 520 | try self.writeSrc(stream, src); | ||
| 521 | }, | ||
| 512 | } | 522 | } |
| 513 | } | 523 | } |
| 514 | 524 |
src/stage1/all_types.hpp+1| ... | @@ -1768,6 +1768,7 @@ enum BuiltinFnId { | ... | @@ -1768,6 +1768,7 @@ enum BuiltinFnId { |
| 1768 | BuiltinFnIdSqrt, | 1768 | BuiltinFnIdSqrt, |
| 1769 | BuiltinFnIdSin, | 1769 | BuiltinFnIdSin, |
| 1770 | BuiltinFnIdCos, | 1770 | BuiltinFnIdCos, |
| 1771 | BuiltinFnIdTan, | ||
| 1771 | BuiltinFnIdExp, | 1772 | BuiltinFnIdExp, |
| 1772 | BuiltinFnIdExp2, | 1773 | BuiltinFnIdExp2, |
| 1773 | BuiltinFnIdLog, | 1774 | BuiltinFnIdLog, |
src/stage1/analyze.cpp+2| ... | @@ -10383,6 +10383,8 @@ const char *float_un_op_to_name(BuiltinFnId op) { | ... | @@ -10383,6 +10383,8 @@ const char *float_un_op_to_name(BuiltinFnId op) { |
| 10383 | return "sin"; | 10383 | return "sin"; |
| 10384 | case BuiltinFnIdCos: | 10384 | case BuiltinFnIdCos: |
| 10385 | return "cos"; | 10385 | return "cos"; |
| 10386 | case BuiltinFnIdTan: | ||
| 10387 | return "tan"; | ||
| 10386 | case BuiltinFnIdExp: | 10388 | case BuiltinFnIdExp: |
| 10387 | return "exp"; | 10389 | return "exp"; |
| 10388 | case BuiltinFnIdExp2: | 10390 | case BuiltinFnIdExp2: |
src/stage1/astgen.cpp+1| ... | @@ -4497,6 +4497,7 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast | ... | @@ -4497,6 +4497,7 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast |
| 4497 | case BuiltinFnIdSqrt: | 4497 | case BuiltinFnIdSqrt: |
| 4498 | case BuiltinFnIdSin: | 4498 | case BuiltinFnIdSin: |
| 4499 | case BuiltinFnIdCos: | 4499 | case BuiltinFnIdCos: |
| 4500 | case BuiltinFnIdTan: | ||
| 4500 | case BuiltinFnIdExp: | 4501 | case BuiltinFnIdExp: |
| 4501 | case BuiltinFnIdExp2: | 4502 | case BuiltinFnIdExp2: |
| 4502 | case BuiltinFnIdLog: | 4503 | case BuiltinFnIdLog: |
src/stage1/codegen.cpp+32-9| ... | @@ -1629,11 +1629,28 @@ static const char *get_compiler_rt_type_abbrev(ZigType *type) { | ... | @@ -1629,11 +1629,28 @@ static const char *get_compiler_rt_type_abbrev(ZigType *type) { |
| 1629 | } | 1629 | } |
| 1630 | } | 1630 | } |
| 1631 | 1631 | ||
| 1632 | static const char *get_math_h_type_abbrev(CodeGen *g, ZigType *float_type) { | 1632 | static const char *libc_float_prefix(CodeGen *g, ZigType *float_type) { |
| 1633 | if (float_type == g->builtin_types.entry_f16) | ||
| 1634 | return "__"; | ||
| 1635 | else if (float_type == g->builtin_types.entry_f32) | ||
| 1636 | return ""; | ||
| 1637 | else if (float_type == g->builtin_types.entry_f64) | ||
| 1638 | return ""; | ||
| 1639 | else if (float_type == g->builtin_types.entry_f80) | ||
| 1640 | return "__"; | ||
| 1641 | else if (float_type == g->builtin_types.entry_c_longdouble) | ||
| 1642 | return "l"; | ||
| 1643 | else if (float_type == g->builtin_types.entry_f128) | ||
| 1644 | return ""; | ||
| 1645 | else | ||
| 1646 | zig_unreachable(); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | static const char *libc_float_suffix(CodeGen *g, ZigType *float_type) { | ||
| 1633 | if (float_type == g->builtin_types.entry_f16) | 1650 | if (float_type == g->builtin_types.entry_f16) |
| 1634 | return "h"; // Non-standard | 1651 | return "h"; // Non-standard |
| 1635 | else if (float_type == g->builtin_types.entry_f32) | 1652 | else if (float_type == g->builtin_types.entry_f32) |
| 1636 | return "s"; | 1653 | return "f"; |
| 1637 | else if (float_type == g->builtin_types.entry_f64) | 1654 | else if (float_type == g->builtin_types.entry_f64) |
| 1638 | return ""; | 1655 | return ""; |
| 1639 | else if (float_type == g->builtin_types.entry_f80) | 1656 | else if (float_type == g->builtin_types.entry_f80) |
| ... | @@ -2992,10 +3009,12 @@ static LLVMValueRef get_soft_float_fn(CodeGen *g, const char *name, int param_co | ... | @@ -2992,10 +3009,12 @@ static LLVMValueRef get_soft_float_fn(CodeGen *g, const char *name, int param_co |
| 2992 | 3009 | ||
| 2993 | static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *operand_type, BuiltinFnId op_id) { | 3010 | static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *operand_type, BuiltinFnId op_id) { |
| 2994 | uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; | 3011 | uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; |
| 3012 | ZigType *scalar_type = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.elem_type : operand_type; | ||
| 2995 | 3013 | ||
| 2996 | char fn_name[64]; | 3014 | char fn_name[64]; |
| 2997 | sprintf(fn_name, "%s%s", float_un_op_to_name(op_id), get_math_h_type_abbrev(g, operand_type)); | 3015 | sprintf(fn_name, "%s%s%s", libc_float_prefix(g, scalar_type), |
| 2998 | LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, operand_type->llvm_type, operand_type->llvm_type); | 3016 | float_un_op_to_name(op_id), libc_float_suffix(g, scalar_type)); |
| 3017 | LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, scalar_type->llvm_type, scalar_type->llvm_type); | ||
| 2999 | 3018 | ||
| 3000 | LLVMValueRef result; | 3019 | LLVMValueRef result; |
| 3001 | if (vector_len == 0) { | 3020 | if (vector_len == 0) { |
| ... | @@ -3018,7 +3037,9 @@ static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *o | ... | @@ -3018,7 +3037,9 @@ static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *o |
| 3018 | assert(operand_type->id == ZigTypeIdFloat || operand_type->id == ZigTypeIdVector); | 3037 | assert(operand_type->id == ZigTypeIdFloat || operand_type->id == ZigTypeIdVector); |
| 3019 | ZigType *elem_type = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.elem_type : operand_type; | 3038 | ZigType *elem_type = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.elem_type : operand_type; |
| 3020 | if ((elem_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) || | 3039 | if ((elem_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) || |
| 3021 | (elem_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target))) { | 3040 | (elem_type == g->builtin_types.entry_f128 && !target_long_double_is_f128(g->zig_target)) || |
| 3041 | op == BuiltinFnIdTan) | ||
| 3042 | { | ||
| 3022 | return gen_soft_float_un_op(g, operand, operand_type, op); | 3043 | return gen_soft_float_un_op(g, operand, operand_type, op); |
| 3023 | } | 3044 | } |
| 3024 | LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op); | 3045 | LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op); |
| ... | @@ -3466,7 +3487,8 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL | ... | @@ -3466,7 +3487,8 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3466 | int param_count = 2; | 3487 | int param_count = 2; |
| 3467 | 3488 | ||
| 3468 | const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type); | 3489 | const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type); |
| 3469 | const char *math_h_type_abbrev = get_math_h_type_abbrev(g, operand_type); | 3490 | const char *math_float_prefix = libc_float_prefix(g, operand_type); |
| 3491 | const char *math_float_suffix = libc_float_suffix(g, operand_type); | ||
| 3470 | 3492 | ||
| 3471 | char fn_name[64]; | 3493 | char fn_name[64]; |
| 3472 | Icmp res_icmp = NONE; | 3494 | Icmp res_icmp = NONE; |
| ... | @@ -3523,10 +3545,10 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL | ... | @@ -3523,10 +3545,10 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3523 | res_icmp = EQ_ONE; | 3545 | res_icmp = EQ_ONE; |
| 3524 | break; | 3546 | break; |
| 3525 | case IrBinOpMaximum: | 3547 | case IrBinOpMaximum: |
| 3526 | sprintf(fn_name, "fmax%s", math_h_type_abbrev); | 3548 | sprintf(fn_name, "%sfmax%s", math_float_prefix, math_float_suffix); |
| 3527 | break; | 3549 | break; |
| 3528 | case IrBinOpMinimum: | 3550 | case IrBinOpMinimum: |
| 3529 | sprintf(fn_name, "fmin%s", math_h_type_abbrev); | 3551 | sprintf(fn_name, "%sfmin%s", math_float_prefix, math_float_suffix); |
| 3530 | break; | 3552 | break; |
| 3531 | case IrBinOpMult: | 3553 | case IrBinOpMult: |
| 3532 | sprintf(fn_name, "__mul%sf3", compiler_rt_type_abbrev); | 3554 | sprintf(fn_name, "__mul%sf3", compiler_rt_type_abbrev); |
| ... | @@ -3545,7 +3567,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL | ... | @@ -3545,7 +3567,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3545 | break; | 3567 | break; |
| 3546 | case IrBinOpRemRem: | 3568 | case IrBinOpRemRem: |
| 3547 | case IrBinOpRemMod: | 3569 | case IrBinOpRemMod: |
| 3548 | sprintf(fn_name, "fmod%s", math_h_type_abbrev); | 3570 | sprintf(fn_name, "%sfmod%s", math_float_prefix, math_float_suffix); |
| 3549 | break; | 3571 | break; |
| 3550 | default: | 3572 | default: |
| 3551 | zig_unreachable(); | 3573 | zig_unreachable(); |
| ... | @@ -9810,6 +9832,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -9810,6 +9832,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 9810 | create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 1); | 9832 | create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 1); |
| 9811 | create_builtin_fn(g, BuiltinFnIdSin, "sin", 1); | 9833 | create_builtin_fn(g, BuiltinFnIdSin, "sin", 1); |
| 9812 | create_builtin_fn(g, BuiltinFnIdCos, "cos", 1); | 9834 | create_builtin_fn(g, BuiltinFnIdCos, "cos", 1); |
| 9835 | create_builtin_fn(g, BuiltinFnIdTan, "tan", 1); | ||
| 9813 | create_builtin_fn(g, BuiltinFnIdExp, "exp", 1); | 9836 | create_builtin_fn(g, BuiltinFnIdExp, "exp", 1); |
| 9814 | create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 1); | 9837 | create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 1); |
| 9815 | create_builtin_fn(g, BuiltinFnIdLog, "log", 1); | 9838 | create_builtin_fn(g, BuiltinFnIdLog, "log", 1); |
src/stage1/ir.cpp+11| ... | @@ -24132,6 +24132,9 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -24132,6 +24132,9 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 24132 | case BuiltinFnIdCos: | 24132 | case BuiltinFnIdCos: |
| 24133 | out_val->data.x_f16 = zig_double_to_f16(cos(zig_f16_to_double(op->data.x_f16))); | 24133 | out_val->data.x_f16 = zig_double_to_f16(cos(zig_f16_to_double(op->data.x_f16))); |
| 24134 | break; | 24134 | break; |
| 24135 | case BuiltinFnIdTan: | ||
| 24136 | out_val->data.x_f16 = zig_double_to_f16(tan(zig_f16_to_double(op->data.x_f16))); | ||
| 24137 | break; | ||
| 24135 | case BuiltinFnIdExp: | 24138 | case BuiltinFnIdExp: |
| 24136 | out_val->data.x_f16 = zig_double_to_f16(exp(zig_f16_to_double(op->data.x_f16))); | 24139 | out_val->data.x_f16 = zig_double_to_f16(exp(zig_f16_to_double(op->data.x_f16))); |
| 24137 | break; | 24140 | break; |
| ... | @@ -24181,6 +24184,9 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -24181,6 +24184,9 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 24181 | case BuiltinFnIdCos: | 24184 | case BuiltinFnIdCos: |
| 24182 | out_val->data.x_f32 = cosf(op->data.x_f32); | 24185 | out_val->data.x_f32 = cosf(op->data.x_f32); |
| 24183 | break; | 24186 | break; |
| 24187 | case BuiltinFnIdTan: | ||
| 24188 | out_val->data.x_f32 = tanf(op->data.x_f32); | ||
| 24189 | break; | ||
| 24184 | case BuiltinFnIdExp: | 24190 | case BuiltinFnIdExp: |
| 24185 | out_val->data.x_f32 = expf(op->data.x_f32); | 24191 | out_val->data.x_f32 = expf(op->data.x_f32); |
| 24186 | break; | 24192 | break; |
| ... | @@ -24230,6 +24236,9 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -24230,6 +24236,9 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 24230 | case BuiltinFnIdCos: | 24236 | case BuiltinFnIdCos: |
| 24231 | out_val->data.x_f64 = cos(op->data.x_f64); | 24237 | out_val->data.x_f64 = cos(op->data.x_f64); |
| 24232 | break; | 24238 | break; |
| 24239 | case BuiltinFnIdTan: | ||
| 24240 | out_val->data.x_f64 = tan(op->data.x_f64); | ||
| 24241 | break; | ||
| 24233 | case BuiltinFnIdExp: | 24242 | case BuiltinFnIdExp: |
| 24234 | out_val->data.x_f64 = exp(op->data.x_f64); | 24243 | out_val->data.x_f64 = exp(op->data.x_f64); |
| 24235 | break; | 24244 | break; |
| ... | @@ -24293,6 +24302,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -24293,6 +24302,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 24293 | case BuiltinFnIdNearbyInt: | 24302 | case BuiltinFnIdNearbyInt: |
| 24294 | case BuiltinFnIdSin: | 24303 | case BuiltinFnIdSin: |
| 24295 | case BuiltinFnIdCos: | 24304 | case BuiltinFnIdCos: |
| 24305 | case BuiltinFnIdTan: | ||
| 24296 | case BuiltinFnIdExp: | 24306 | case BuiltinFnIdExp: |
| 24297 | case BuiltinFnIdExp2: | 24307 | case BuiltinFnIdExp2: |
| 24298 | case BuiltinFnIdLog: | 24308 | case BuiltinFnIdLog: |
| ... | @@ -24337,6 +24347,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -24337,6 +24347,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 24337 | case BuiltinFnIdNearbyInt: | 24347 | case BuiltinFnIdNearbyInt: |
| 24338 | case BuiltinFnIdSin: | 24348 | case BuiltinFnIdSin: |
| 24339 | case BuiltinFnIdCos: | 24349 | case BuiltinFnIdCos: |
| 24350 | case BuiltinFnIdTan: | ||
| 24340 | case BuiltinFnIdExp: | 24351 | case BuiltinFnIdExp: |
| 24341 | case BuiltinFnIdExp2: | 24352 | case BuiltinFnIdExp2: |
| 24342 | case BuiltinFnIdLog: | 24353 | case BuiltinFnIdLog: |
src/value.zig+38| ... | @@ -4473,6 +4473,44 @@ pub const Value = extern union { | ... | @@ -4473,6 +4473,44 @@ pub const Value = extern union { |
| 4473 | } | 4473 | } |
| 4474 | } | 4474 | } |
| 4475 | 4475 | ||
| 4476 | pub fn tan(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 4477 | if (float_type.zigTypeTag() == .Vector) { | ||
| 4478 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | ||
| 4479 | for (result_data) |*scalar, i| { | ||
| 4480 | scalar.* = try tanScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | ||
| 4481 | } | ||
| 4482 | return Value.Tag.aggregate.create(arena, result_data); | ||
| 4483 | } | ||
| 4484 | return tanScalar(val, float_type, arena, target); | ||
| 4485 | } | ||
| 4486 | |||
| 4487 | pub fn tanScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | ||
| 4488 | switch (float_type.floatBits(target)) { | ||
| 4489 | 16 => { | ||
| 4490 | const f = val.toFloat(f16); | ||
| 4491 | return Value.Tag.float_16.create(arena, @tan(f)); | ||
| 4492 | }, | ||
| 4493 | 32 => { | ||
| 4494 | const f = val.toFloat(f32); | ||
| 4495 | return Value.Tag.float_32.create(arena, @tan(f)); | ||
| 4496 | }, | ||
| 4497 | 64 => { | ||
| 4498 | const f = val.toFloat(f64); | ||
| 4499 | return Value.Tag.float_64.create(arena, @tan(f)); | ||
| 4500 | }, | ||
| 4501 | 80 => { | ||
| 4502 | const f = val.toFloat(f80); | ||
| 4503 | return Value.Tag.float_80.create(arena, @tan(f)); | ||
| 4504 | }, | ||
| 4505 | 128 => { | ||
| 4506 | const f = val.toFloat(f128); | ||
| 4507 | return Value.Tag.float_128.create(arena, @tan(f)); | ||
| 4508 | }, | ||
| 4509 | else => unreachable, | ||
| 4510 | } | ||
| 4511 | } | ||
| 4512 | |||
| 4513 | |||
| 4476 | pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | 4514 | pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4477 | if (float_type.zigTypeTag() == .Vector) { | 4515 | if (float_type.zigTypeTag() == .Vector) { |
| 4478 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4516 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
test/behavior/bugs/920.zig+2-3| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const math = std.math; | ||
| 3 | const Random = std.rand.Random; | 2 | const Random = std.rand.Random; |
| 4 | 3 | ||
| 5 | const ZigTable = struct { | 4 | const ZigTable = struct { |
| ... | @@ -40,10 +39,10 @@ const norm_r = 3.6541528853610088; | ... | @@ -40,10 +39,10 @@ const norm_r = 3.6541528853610088; |
| 40 | const norm_v = 0.00492867323399; | 39 | const norm_v = 0.00492867323399; |
| 41 | 40 | ||
| 42 | fn norm_f(x: f64) f64 { | 41 | fn norm_f(x: f64) f64 { |
| 43 | return math.exp(-x * x / 2.0); | 42 | return @exp(-x * x / 2.0); |
| 44 | } | 43 | } |
| 45 | fn norm_f_inv(y: f64) f64 { | 44 | fn norm_f_inv(y: f64) f64 { |
| 46 | return math.sqrt(-2.0 * math.ln(y)); | 45 | return @sqrt(-2.0 * @log(y)); |
| 47 | } | 46 | } |
| 48 | fn norm_zero_case(random: *Random, u: f64) f64 { | 47 | fn norm_zero_case(random: *Random, u: f64) f64 { |
| 49 | _ = random; | 48 | _ = random; |