authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-27 16:45:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-27 16:45:23-07:00
log09f1d62bdfb5794534b21d1cd9dafc4822697d60
tree437f6c19a6f0f16ef29fb91513176bb8aa0c91f0
parentc4eaff6665132287d05272bef8890e4607ff017c

add new builtin function `@tan`

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#}
80328032
...@@ -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 }
5050
51 // Kahan's algorithm51 // 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 }
9393
94 // Kahan's algorithm94 // 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: off912 // 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: on943 // 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}
69406941
6941fn zirFieldCallBindNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6942fn 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();
69446945
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 whether410 /// 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,
19311934
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 };
29652968
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-standard5556 16 => "h", // Non-standard
5556 32 => "s",5557 32 => "f",
5557 64 => "",5558 64 => "",
5558 80 => "x", // Non-standard5559 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 };
56665668
...@@ -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);
56865688
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 intrinsics5692 // 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 {
400401
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),
405405
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 }
514524
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}
16311631
1632static const char *get_math_h_type_abbrev(CodeGen *g, ZigType *float_type) {1632static 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
1649static 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-standard1651 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
29923009
2993static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *operand_type, BuiltinFnId op_id) {3010static 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;
29953013
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);
29993018
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;
34673488
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);
34703492
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 }
44754475
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 @@
1const std = @import("std");1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;2const Random = std.rand.Random;
43
5const ZigTable = struct {4const ZigTable = struct {
...@@ -40,10 +39,10 @@ const norm_r = 3.6541528853610088;...@@ -40,10 +39,10 @@ const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;39const norm_v = 0.00492867323399;
4140
42fn norm_f(x: f64) f64 {41fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);42 return @exp(-x * x / 2.0);
44}43}
45fn norm_f_inv(y: f64) f64 {44fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));45 return @sqrt(-2.0 * @log(y));
47}46}
48fn norm_zero_case(random: *Random, u: f64) f64 {47fn norm_zero_case(random: *Random, u: f64) f64 {
49 _ = random;48 _ = random;