| ... | @@ -18,7 +18,6 @@ const Compilation = @import("../../Compilation.zig"); | ... | @@ -18,7 +18,6 @@ const Compilation = @import("../../Compilation.zig"); |
| 18 | const link = @import("../../link.zig"); | 18 | const link = @import("../../link.zig"); |
| 19 | const Air = @import("../../Air.zig"); | 19 | const Air = @import("../../Air.zig"); |
| 20 | const Liveness = @import("../../Liveness.zig"); | 20 | const Liveness = @import("../../Liveness.zig"); |
| 21 | const target_util = @import("../../target.zig"); | | |
| 22 | const Mir = @import("Mir.zig"); | 21 | const Mir = @import("Mir.zig"); |
| 23 | const Emit = @import("Emit.zig"); | 22 | const Emit = @import("Emit.zig"); |
| 24 | const abi = @import("abi.zig"); | 23 | const abi = @import("abi.zig"); |
| ... | @@ -27,6 +26,12 @@ const errUnionPayloadOffset = codegen.errUnionPayloadOffset; | ... | @@ -27,6 +26,12 @@ const errUnionPayloadOffset = codegen.errUnionPayloadOffset; |
| 27 | const errUnionErrorOffset = codegen.errUnionErrorOffset; | 26 | const errUnionErrorOffset = codegen.errUnionErrorOffset; |
| 28 | const Wasm = link.File.Wasm; | 27 | const Wasm = link.File.Wasm; |
| 29 | | 28 | |
| | 29 | const target_util = @import("../../target.zig"); |
| | 30 | const libcFloatPrefix = target_util.libcFloatPrefix; |
| | 31 | const libcFloatSuffix = target_util.libcFloatSuffix; |
| | 32 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; |
| | 33 | const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| | 34 | |
| 30 | /// Reference to the function declaration the code | 35 | /// Reference to the function declaration the code |
| 31 | /// section belongs to | 36 | /// section belongs to |
| 32 | owner_nav: InternPool.Nav.Index, | 37 | owner_nav: InternPool.Nav.Index, |
| ... | @@ -854,7 +859,6 @@ fn processDeath(cg: *CodeGen, ref: Air.Inst.Ref) void { | ... | @@ -854,7 +859,6 @@ fn processDeath(cg: *CodeGen, ref: Air.Inst.Ref) void { |
| 854 | } | 859 | } |
| 855 | } | 860 | } |
| 856 | | 861 | |
| 857 | /// Appends a MIR instruction and returns its index within the list of instructions | | |
| 858 | fn addInst(cg: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!void { | 862 | fn addInst(cg: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!void { |
| 859 | try cg.mir_instructions.append(cg.gpa, inst); | 863 | try cg.mir_instructions.append(cg.gpa, inst); |
| 860 | } | 864 | } |
| ... | @@ -873,14 +877,6 @@ fn addLabel(cg: *CodeGen, tag: Mir.Inst.Tag, label: u32) error{OutOfMemory}!void | ... | @@ -873,14 +877,6 @@ fn addLabel(cg: *CodeGen, tag: Mir.Inst.Tag, label: u32) error{OutOfMemory}!void |
| 873 | try cg.addInst(.{ .tag = tag, .data = .{ .label = label } }); | 877 | try cg.addInst(.{ .tag = tag, .data = .{ .label = label } }); |
| 874 | } | 878 | } |
| 875 | | 879 | |
| 876 | fn addIpIndex(cg: *CodeGen, tag: Mir.Inst.Tag, i: InternPool.Index) Allocator.Error!void { | | |
| 877 | try cg.addInst(.{ .tag = tag, .data = .{ .ip_index = i } }); | | |
| 878 | } | | |
| 879 | | | |
| 880 | fn addNav(cg: *CodeGen, tag: Mir.Inst.Tag, i: InternPool.Nav.Index) Allocator.Error!void { | | |
| 881 | try cg.addInst(.{ .tag = tag, .data = .{ .nav_index = i } }); | | |
| 882 | } | | |
| 883 | | | |
| 884 | /// Accepts an unsigned 32bit integer rather than a signed integer to | 880 | /// Accepts an unsigned 32bit integer rather than a signed integer to |
| 885 | /// prevent us from having to bitcast multiple times as most values | 881 | /// prevent us from having to bitcast multiple times as most values |
| 886 | /// within codegen are represented as unsigned rather than signed. | 882 | /// within codegen are represented as unsigned rather than signed. |
| ... | @@ -1887,8 +1883,8 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1887,8 +1883,8 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1887 | .shl_sat => cg.airShlSat(inst), | 1883 | .shl_sat => cg.airShlSat(inst), |
| 1888 | .shr, .shr_exact => cg.airBinOp(inst, .shr), | 1884 | .shr, .shr_exact => cg.airBinOp(inst, .shr), |
| 1889 | .xor => cg.airBinOp(inst, .xor), | 1885 | .xor => cg.airBinOp(inst, .xor), |
| 1890 | .max => cg.airMaxMin(inst, .max), | 1886 | .max => cg.airMaxMin(inst, .fmax, .gt), |
| 1891 | .min => cg.airMaxMin(inst, .min), | 1887 | .min => cg.airMaxMin(inst, .fmin, .lt), |
| 1892 | .mul_add => cg.airMulAdd(inst), | 1888 | .mul_add => cg.airMulAdd(inst), |
| 1893 | | 1889 | |
| 1894 | .sqrt => cg.airUnaryFloatOp(inst, .sqrt), | 1890 | .sqrt => cg.airUnaryFloatOp(inst, .sqrt), |
| ... | @@ -2263,7 +2259,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie | ... | @@ -2263,7 +2259,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 2263 | } | 2259 | } |
| 2264 | | 2260 | |
| 2265 | if (callee) |nav_index| { | 2261 | if (callee) |nav_index| { |
| 2266 | try cg.addNav(.call_nav, nav_index); | 2262 | try cg.addInst(.{ .tag = .call_nav, .data = .{ .nav_index = nav_index } }); |
| 2267 | } else { | 2263 | } else { |
| 2268 | // in this case we call a function pointer | 2264 | // in this case we call a function pointer |
| 2269 | // so load its value onto the stack | 2265 | // so load its value onto the stack |
| ... | @@ -2669,20 +2665,20 @@ fn binOpBigInt(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr | ... | @@ -2669,20 +2665,20 @@ fn binOpBigInt(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr |
| 2669 | } | 2665 | } |
| 2670 | | 2666 | |
| 2671 | switch (op) { | 2667 | switch (op) { |
| 2672 | .mul => return cg.callIntrinsic("__multi3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), | 2668 | .mul => return cg.callIntrinsic(.__multi3, &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), |
| 2673 | .div => switch (int_info.signedness) { | 2669 | .div => switch (int_info.signedness) { |
| 2674 | .signed => return cg.callIntrinsic("__divti3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), | 2670 | .signed => return cg.callIntrinsic(.__divti3, &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), |
| 2675 | .unsigned => return cg.callIntrinsic("__udivti3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), | 2671 | .unsigned => return cg.callIntrinsic(.__udivti3, &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), |
| 2676 | }, | 2672 | }, |
| 2677 | .rem => switch (int_info.signedness) { | 2673 | .rem => switch (int_info.signedness) { |
| 2678 | .signed => return cg.callIntrinsic("__modti3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), | 2674 | .signed => return cg.callIntrinsic(.__modti3, &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), |
| 2679 | .unsigned => return cg.callIntrinsic("__umodti3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), | 2675 | .unsigned => return cg.callIntrinsic(.__umodti3, &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }), |
| 2680 | }, | 2676 | }, |
| 2681 | .shr => switch (int_info.signedness) { | 2677 | .shr => switch (int_info.signedness) { |
| 2682 | .signed => return cg.callIntrinsic("__ashrti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }), | 2678 | .signed => return cg.callIntrinsic(.__ashrti3, &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }), |
| 2683 | .unsigned => return cg.callIntrinsic("__lshrti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }), | 2679 | .unsigned => return cg.callIntrinsic(.__lshrti3, &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }), |
| 2684 | }, | 2680 | }, |
| 2685 | .shl => return cg.callIntrinsic("__ashlti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }), | 2681 | .shl => return cg.callIntrinsic(.__ashlti3, &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }), |
| 2686 | .@"and", .@"or", .xor => { | 2682 | .@"and", .@"or", .xor => { |
| 2687 | const result = try cg.allocStack(ty); | 2683 | const result = try cg.allocStack(ty); |
| 2688 | try cg.emitWValue(result); | 2684 | try cg.emitWValue(result); |
| ... | @@ -2802,6 +2798,46 @@ const FloatOp = enum { | ... | @@ -2802,6 +2798,46 @@ const FloatOp = enum { |
| 2802 | => null, | 2798 | => null, |
| 2803 | }; | 2799 | }; |
| 2804 | } | 2800 | } |
| | 2801 | |
| | 2802 | fn intrinsic(op: FloatOp, bits: u16) Mir.Intrinsic { |
| | 2803 | return switch (op) { |
| | 2804 | inline .add, .sub, .div, .mul => |ct_op| switch (bits) { |
| | 2805 | inline 16, 80, 128 => |ct_bits| @field( |
| | 2806 | Mir.Intrinsic, |
| | 2807 | "__" ++ @tagName(ct_op) ++ compilerRtFloatAbbrev(ct_bits) ++ "f3", |
| | 2808 | ), |
| | 2809 | else => unreachable, |
| | 2810 | }, |
| | 2811 | |
| | 2812 | inline .ceil, |
| | 2813 | .cos, |
| | 2814 | .exp, |
| | 2815 | .exp2, |
| | 2816 | .fabs, |
| | 2817 | .floor, |
| | 2818 | .fma, |
| | 2819 | .fmax, |
| | 2820 | .fmin, |
| | 2821 | .fmod, |
| | 2822 | .log, |
| | 2823 | .log10, |
| | 2824 | .log2, |
| | 2825 | .round, |
| | 2826 | .sin, |
| | 2827 | .sqrt, |
| | 2828 | .tan, |
| | 2829 | .trunc, |
| | 2830 | => |ct_op| switch (bits) { |
| | 2831 | inline 16, 80, 128 => |ct_bits| @field( |
| | 2832 | Mir.Intrinsic, |
| | 2833 | libcFloatPrefix(ct_bits) ++ @tagName(ct_op) ++ libcFloatSuffix(ct_bits), |
| | 2834 | ), |
| | 2835 | else => unreachable, |
| | 2836 | }, |
| | 2837 | |
| | 2838 | .neg => unreachable, |
| | 2839 | }; |
| | 2840 | } |
| 2805 | }; | 2841 | }; |
| 2806 | | 2842 | |
| 2807 | fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 2843 | fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | @@ -2919,44 +2955,12 @@ fn floatOp(cg: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) Inne | ... | @@ -2919,44 +2955,12 @@ fn floatOp(cg: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) Inne |
| 2919 | } | 2955 | } |
| 2920 | } | 2956 | } |
| 2921 | | 2957 | |
| 2922 | var fn_name_buf: [64]u8 = undefined; | 2958 | const intrinsic = float_op.intrinsic(float_bits); |
| 2923 | const fn_name = switch (float_op) { | | |
| 2924 | .add, | | |
| 2925 | .sub, | | |
| 2926 | .div, | | |
| 2927 | .mul, | | |
| 2928 | => std.fmt.bufPrint(&fn_name_buf, "__{s}{s}f3", .{ | | |
| 2929 | @tagName(float_op), target_util.compilerRtFloatAbbrev(float_bits), | | |
| 2930 | }) catch unreachable, | | |
| 2931 | | | |
| 2932 | .ceil, | | |
| 2933 | .cos, | | |
| 2934 | .exp, | | |
| 2935 | .exp2, | | |
| 2936 | .fabs, | | |
| 2937 | .floor, | | |
| 2938 | .fma, | | |
| 2939 | .fmax, | | |
| 2940 | .fmin, | | |
| 2941 | .fmod, | | |
| 2942 | .log, | | |
| 2943 | .log10, | | |
| 2944 | .log2, | | |
| 2945 | .round, | | |
| 2946 | .sin, | | |
| 2947 | .sqrt, | | |
| 2948 | .tan, | | |
| 2949 | .trunc, | | |
| 2950 | => std.fmt.bufPrint(&fn_name_buf, "{s}{s}{s}", .{ | | |
| 2951 | target_util.libcFloatPrefix(float_bits), @tagName(float_op), target_util.libcFloatSuffix(float_bits), | | |
| 2952 | }) catch unreachable, | | |
| 2953 | .neg => unreachable, // handled above | | |
| 2954 | }; | | |
| 2955 | | 2959 | |
| 2956 | // fma requires three operands | 2960 | // fma requires three operands |
| 2957 | var param_types_buffer: [3]InternPool.Index = .{ ty.ip_index, ty.ip_index, ty.ip_index }; | 2961 | var param_types_buffer: [3]InternPool.Index = .{ ty.ip_index, ty.ip_index, ty.ip_index }; |
| 2958 | const param_types = param_types_buffer[0..args.len]; | 2962 | const param_types = param_types_buffer[0..args.len]; |
| 2959 | return cg.callIntrinsic(fn_name, param_types, ty, args); | 2963 | return cg.callIntrinsic(intrinsic, param_types, ty, args); |
| 2960 | } | 2964 | } |
| 2961 | | 2965 | |
| 2962 | /// NOTE: The result value remains on top of the stack. | 2966 | /// NOTE: The result value remains on top of the stack. |
| ... | @@ -3605,12 +3609,8 @@ fn cmpFloat(cg: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math.C | ... | @@ -3605,12 +3609,8 @@ fn cmpFloat(cg: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math.C |
| 3605 | return .stack; | 3609 | return .stack; |
| 3606 | }, | 3610 | }, |
| 3607 | 80, 128 => { | 3611 | 80, 128 => { |
| 3608 | var fn_name_buf: [32]u8 = undefined; | 3612 | const intrinsic = floatCmpIntrinsic(cmp_op, float_bits); |
| 3609 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "__{s}{s}f2", .{ | 3613 | const result = try cg.callIntrinsic(intrinsic, &.{ ty.ip_index, ty.ip_index }, Type.bool, &.{ lhs, rhs }); |
| 3610 | @tagName(op), target_util.compilerRtFloatAbbrev(float_bits), | | |
| 3611 | }) catch unreachable; | | |
| 3612 | | | |
| 3613 | const result = try cg.callIntrinsic(fn_name, &.{ ty.ip_index, ty.ip_index }, Type.bool, &.{ lhs, rhs }); | | |
| 3614 | return cg.cmp(result, .{ .imm32 = 0 }, Type.i32, cmp_op); | 3614 | return cg.cmp(result, .{ .imm32 = 0 }, Type.i32, cmp_op); |
| 3615 | }, | 3615 | }, |
| 3616 | else => unreachable, | 3616 | else => unreachable, |
| ... | @@ -5001,19 +5001,26 @@ fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5001,19 +5001,26 @@ fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5001 | } | 5001 | } |
| 5002 | | 5002 | |
| 5003 | if ((op_bits != 32 and op_bits != 64) or dest_info.bits > 64) { | 5003 | if ((op_bits != 32 and op_bits != 64) or dest_info.bits > 64) { |
| 5004 | const dest_bitsize = if (dest_info.bits <= 16) 16 else std.math.ceilPowerOfTwoAssert(u16, dest_info.bits); | 5004 | const dest_bitsize = if (dest_info.bits <= 32) 32 else std.math.ceilPowerOfTwoAssert(u16, dest_info.bits); |
| 5005 | | 5005 | |
| 5006 | var fn_name_buf: [16]u8 = undefined; | 5006 | const intrinsic = switch (dest_info.signedness) { |
| 5007 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "__fix{s}{s}f{s}i", .{ | 5007 | inline .signed, .unsigned => |ct_s| switch (op_bits) { |
| 5008 | switch (dest_info.signedness) { | 5008 | inline 16, 32, 64, 80, 128 => |ct_op_bits| switch (dest_bitsize) { |
| 5009 | .signed => "", | 5009 | inline 32, 64, 128 => |ct_dest_bits| @field( |
| 5010 | .unsigned => "uns", | 5010 | Mir.Intrinsic, |
| | 5011 | "__fix" ++ switch (ct_s) { |
| | 5012 | .signed => "", |
| | 5013 | .unsigned => "uns", |
| | 5014 | } ++ |
| | 5015 | compilerRtFloatAbbrev(ct_op_bits) ++ "f" ++ |
| | 5016 | compilerRtIntAbbrev(ct_dest_bits) ++ "i", |
| | 5017 | ), |
| | 5018 | else => unreachable, |
| | 5019 | }, |
| | 5020 | else => unreachable, |
| 5011 | }, | 5021 | }, |
| 5012 | target_util.compilerRtFloatAbbrev(op_bits), | 5022 | }; |
| 5013 | target_util.compilerRtIntAbbrev(dest_bitsize), | 5023 | const result = try cg.callIntrinsic(intrinsic, &.{op_ty.ip_index}, dest_ty, &.{operand}); |
| 5014 | }) catch unreachable; | | |
| 5015 | | | |
| 5016 | const result = try cg.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand}); | | |
| 5017 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 5024 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5018 | } | 5025 | } |
| 5019 | | 5026 | |
| ... | @@ -5046,19 +5053,27 @@ fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5046,19 +5053,27 @@ fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5046 | } | 5053 | } |
| 5047 | | 5054 | |
| 5048 | if (op_info.bits > 64 or (dest_bits > 64 or dest_bits < 32)) { | 5055 | if (op_info.bits > 64 or (dest_bits > 64 or dest_bits < 32)) { |
| 5049 | const op_bitsize = if (op_info.bits <= 16) 16 else std.math.ceilPowerOfTwoAssert(u16, op_info.bits); | 5056 | const op_bitsize = if (op_info.bits <= 32) 32 else std.math.ceilPowerOfTwoAssert(u16, op_info.bits); |
| 5050 | | 5057 | |
| 5051 | var fn_name_buf: [16]u8 = undefined; | 5058 | const intrinsic = switch (op_info.signedness) { |
| 5052 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "__float{s}{s}i{s}f", .{ | 5059 | inline .signed, .unsigned => |ct_s| switch (op_bitsize) { |
| 5053 | switch (op_info.signedness) { | 5060 | inline 32, 64, 128 => |ct_int_bits| switch (dest_bits) { |
| 5054 | .signed => "", | 5061 | inline 16, 32, 64, 80, 128 => |ct_float_bits| @field( |
| 5055 | .unsigned => "un", | 5062 | Mir.Intrinsic, |
| | 5063 | "__float" ++ switch (ct_s) { |
| | 5064 | .signed => "", |
| | 5065 | .unsigned => "un", |
| | 5066 | } ++ |
| | 5067 | compilerRtIntAbbrev(ct_int_bits) ++ "i" ++ |
| | 5068 | compilerRtFloatAbbrev(ct_float_bits) ++ "f", |
| | 5069 | ), |
| | 5070 | else => unreachable, |
| | 5071 | }, |
| | 5072 | else => unreachable, |
| 5056 | }, | 5073 | }, |
| 5057 | target_util.compilerRtIntAbbrev(op_bitsize), | 5074 | }; |
| 5058 | target_util.compilerRtFloatAbbrev(dest_bits), | | |
| 5059 | }) catch unreachable; | | |
| 5060 | | 5075 | |
| 5061 | const result = try cg.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand}); | 5076 | const result = try cg.callIntrinsic(intrinsic, &.{op_ty.ip_index}, dest_ty, &.{operand}); |
| 5062 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 5077 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5063 | } | 5078 | } |
| 5064 | | 5079 | |
| ... | @@ -5577,39 +5592,49 @@ fn airFpext(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5577,39 +5592,49 @@ fn airFpext(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5577 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 5592 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5578 | } | 5593 | } |
| 5579 | | 5594 | |
| 5580 | /// Extends a float from a given `Type` to a larger wanted `Type` | 5595 | /// Extends a float from a given `Type` to a larger wanted `Type`, leaving the |
| 5581 | /// NOTE: Leaves the result on the stack | 5596 | /// result on the stack. |
| 5582 | fn fpext(cg: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { | 5597 | fn fpext(cg: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { |
| 5583 | const given_bits = given.floatBits(cg.target.*); | 5598 | const given_bits = given.floatBits(cg.target.*); |
| 5584 | const wanted_bits = wanted.floatBits(cg.target.*); | 5599 | const wanted_bits = wanted.floatBits(cg.target.*); |
| 5585 | | 5600 | |
| 5586 | if (wanted_bits == 64 and given_bits == 32) { | 5601 | const intrinsic: Mir.Intrinsic = switch (given_bits) { |
| 5587 | try cg.emitWValue(operand); | 5602 | 16 => switch (wanted_bits) { |
| 5588 | try cg.addTag(.f64_promote_f32); | 5603 | 32 => { |
| 5589 | return .stack; | 5604 | assert(.stack == try cg.callIntrinsic(.__extendhfsf2, &.{.f16_type}, Type.f32, &.{operand})); |
| 5590 | } else if (given_bits == 16 and wanted_bits <= 64) { | 5605 | return .stack; |
| 5591 | // call __extendhfsf2(f16) f32 | 5606 | }, |
| 5592 | const f32_result = try cg.callIntrinsic( | 5607 | 64 => { |
| 5593 | "__extendhfsf2", | 5608 | assert(.stack == try cg.callIntrinsic(.__extendhfsf2, &.{.f16_type}, Type.f32, &.{operand})); |
| 5594 | &.{.f16_type}, | 5609 | try cg.addTag(.f64_promote_f32); |
| 5595 | Type.f32, | 5610 | return .stack; |
| 5596 | &.{operand}, | 5611 | }, |
| 5597 | ); | 5612 | 80 => .__extendhfxf2, |
| 5598 | assert(f32_result == .stack); | 5613 | 128 => .__extendhftf2, |
| 5599 | | 5614 | else => unreachable, |
| 5600 | if (wanted_bits == 64) { | 5615 | }, |
| 5601 | try cg.addTag(.f64_promote_f32); | 5616 | 32 => switch (wanted_bits) { |
| 5602 | } | 5617 | 64 => { |
| 5603 | return .stack; | 5618 | try cg.emitWValue(operand); |
| 5604 | } | 5619 | try cg.addTag(.f64_promote_f32); |
| 5605 | | 5620 | return .stack; |
| 5606 | var fn_name_buf: [13]u8 = undefined; | 5621 | }, |
| 5607 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "__extend{s}f{s}f2", .{ | 5622 | 80 => .__extendsfxf2, |
| 5608 | target_util.compilerRtFloatAbbrev(given_bits), | 5623 | 128 => .__extendsftf2, |
| 5609 | target_util.compilerRtFloatAbbrev(wanted_bits), | 5624 | else => unreachable, |
| 5610 | }) catch unreachable; | 5625 | }, |
| 5611 | | 5626 | 64 => switch (wanted_bits) { |
| 5612 | return cg.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand}); | 5627 | 80 => .__extenddfxf2, |
| | 5628 | 128 => .__extenddftf2, |
| | 5629 | else => unreachable, |
| | 5630 | }, |
| | 5631 | 80 => switch (wanted_bits) { |
| | 5632 | 128 => .__extendxftf2, |
| | 5633 | else => unreachable, |
| | 5634 | }, |
| | 5635 | else => unreachable, |
| | 5636 | }; |
| | 5637 | return cg.callIntrinsic(intrinsic, &.{given.ip_index}, wanted, &.{operand}); |
| 5613 | } | 5638 | } |
| 5614 | | 5639 | |
| 5615 | fn airFptrunc(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5640 | fn airFptrunc(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | @@ -5621,34 +5646,48 @@ fn airFptrunc(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5621,34 +5646,48 @@ fn airFptrunc(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5621 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 5646 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5622 | } | 5647 | } |
| 5623 | | 5648 | |
| 5624 | /// Truncates a float from a given `Type` to its wanted `Type` | 5649 | /// Truncates a float from a given `Type` to its wanted `Type`, leaving the |
| 5625 | /// NOTE: The result value remains on the stack | 5650 | /// result on the stack. |
| 5626 | fn fptrunc(cg: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { | 5651 | fn fptrunc(cg: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { |
| 5627 | const given_bits = given.floatBits(cg.target.*); | 5652 | const given_bits = given.floatBits(cg.target.*); |
| 5628 | const wanted_bits = wanted.floatBits(cg.target.*); | 5653 | const wanted_bits = wanted.floatBits(cg.target.*); |
| 5629 | | 5654 | |
| 5630 | if (wanted_bits == 32 and given_bits == 64) { | 5655 | const intrinsic: Mir.Intrinsic = switch (given_bits) { |
| 5631 | try cg.emitWValue(operand); | 5656 | 32 => switch (wanted_bits) { |
| 5632 | try cg.addTag(.f32_demote_f64); | 5657 | 16 => { |
| 5633 | return .stack; | 5658 | return cg.callIntrinsic(.__truncsfhf2, &.{.f32_type}, Type.f16, &.{operand}); |
| 5634 | } else if (wanted_bits == 16 and given_bits <= 64) { | 5659 | }, |
| 5635 | const op: WValue = if (given_bits == 64) blk: { | 5660 | else => unreachable, |
| 5636 | try cg.emitWValue(operand); | 5661 | }, |
| 5637 | try cg.addTag(.f32_demote_f64); | 5662 | 64 => switch (wanted_bits) { |
| 5638 | break :blk .stack; | 5663 | 16 => { |
| 5639 | } else operand; | 5664 | try cg.emitWValue(operand); |
| 5640 | | 5665 | try cg.addTag(.f32_demote_f64); |
| 5641 | // call __truncsfhf2(f32) f16 | 5666 | return cg.callIntrinsic(.__truncsfhf2, &.{.f32_type}, Type.f16, &.{.stack}); |
| 5642 | return cg.callIntrinsic("__truncsfhf2", &.{.f32_type}, Type.f16, &.{op}); | 5667 | }, |
| 5643 | } | 5668 | 32 => { |
| 5644 | | 5669 | try cg.emitWValue(operand); |
| 5645 | var fn_name_buf: [12]u8 = undefined; | 5670 | try cg.addTag(.f32_demote_f64); |
| 5646 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "__trunc{s}f{s}f2", .{ | 5671 | return .stack; |
| 5647 | target_util.compilerRtFloatAbbrev(given_bits), | 5672 | }, |
| 5648 | target_util.compilerRtFloatAbbrev(wanted_bits), | 5673 | else => unreachable, |
| 5649 | }) catch unreachable; | 5674 | }, |
| 5650 | | 5675 | 80 => switch (wanted_bits) { |
| 5651 | return cg.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand}); | 5676 | 16 => .__truncxfhf2, |
| | 5677 | 32 => .__truncxfsf2, |
| | 5678 | 64 => .__truncxfdf2, |
| | 5679 | else => unreachable, |
| | 5680 | }, |
| | 5681 | 128 => switch (wanted_bits) { |
| | 5682 | 16 => .__trunctfhf2, |
| | 5683 | 32 => .__trunctfsf2, |
| | 5684 | 64 => .__trunctfdf2, |
| | 5685 | 80 => .__trunctfxf2, |
| | 5686 | else => unreachable, |
| | 5687 | }, |
| | 5688 | else => unreachable, |
| | 5689 | }; |
| | 5690 | return cg.callIntrinsic(intrinsic, &.{given.ip_index}, wanted, &.{operand}); |
| 5652 | } | 5691 | } |
| 5653 | | 5692 | |
| 5654 | fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5693 | fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | @@ -5823,7 +5862,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5823,7 +5862,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5823 | switch (wasm_bits) { | 5862 | switch (wasm_bits) { |
| 5824 | 32 => { | 5863 | 32 => { |
| 5825 | const intrin_ret = try cg.callIntrinsic( | 5864 | const intrin_ret = try cg.callIntrinsic( |
| 5826 | "__bitreversesi2", | 5865 | .__bitreversesi2, |
| 5827 | &.{.u32_type}, | 5866 | &.{.u32_type}, |
| 5828 | Type.u32, | 5867 | Type.u32, |
| 5829 | &.{operand}, | 5868 | &.{operand}, |
| ... | @@ -5836,7 +5875,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5836,7 +5875,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5836 | }, | 5875 | }, |
| 5837 | 64 => { | 5876 | 64 => { |
| 5838 | const intrin_ret = try cg.callIntrinsic( | 5877 | const intrin_ret = try cg.callIntrinsic( |
| 5839 | "__bitreversedi2", | 5878 | .__bitreversedi2, |
| 5840 | &.{.u64_type}, | 5879 | &.{.u64_type}, |
| 5841 | Type.u64, | 5880 | Type.u64, |
| 5842 | &.{operand}, | 5881 | &.{operand}, |
| ... | @@ -5853,7 +5892,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5853,7 +5892,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5853 | try cg.emitWValue(result); | 5892 | try cg.emitWValue(result); |
| 5854 | const first_half = try cg.load(operand, Type.u64, 8); | 5893 | const first_half = try cg.load(operand, Type.u64, 8); |
| 5855 | const intrin_ret_first = try cg.callIntrinsic( | 5894 | const intrin_ret_first = try cg.callIntrinsic( |
| 5856 | "__bitreversedi2", | 5895 | .__bitreversedi2, |
| 5857 | &.{.u64_type}, | 5896 | &.{.u64_type}, |
| 5858 | Type.u64, | 5897 | Type.u64, |
| 5859 | &.{first_half}, | 5898 | &.{first_half}, |
| ... | @@ -5866,7 +5905,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5866,7 +5905,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5866 | try cg.emitWValue(result); | 5905 | try cg.emitWValue(result); |
| 5867 | const second_half = try cg.load(operand, Type.u64, 0); | 5906 | const second_half = try cg.load(operand, Type.u64, 0); |
| 5868 | const intrin_ret_second = try cg.callIntrinsic( | 5907 | const intrin_ret_second = try cg.callIntrinsic( |
| 5869 | "__bitreversedi2", | 5908 | .__bitreversedi2, |
| 5870 | &.{.u64_type}, | 5909 | &.{.u64_type}, |
| 5871 | Type.u64, | 5910 | Type.u64, |
| 5872 | &.{second_half}, | 5911 | &.{second_half}, |
| ... | @@ -6114,19 +6153,19 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6114,19 +6153,19 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6114 | defer rhs_msb.free(cg); | 6153 | defer rhs_msb.free(cg); |
| 6115 | | 6154 | |
| 6116 | const cross_1 = try cg.callIntrinsic( | 6155 | const cross_1 = try cg.callIntrinsic( |
| 6117 | "__multi3", | 6156 | .__multi3, |
| 6118 | &[_]InternPool.Index{.i64_type} ** 4, | 6157 | &[_]InternPool.Index{.i64_type} ** 4, |
| 6119 | Type.i128, | 6158 | Type.i128, |
| 6120 | &.{ lhs_msb, zero, rhs_lsb, zero }, | 6159 | &.{ lhs_msb, zero, rhs_lsb, zero }, |
| 6121 | ); | 6160 | ); |
| 6122 | const cross_2 = try cg.callIntrinsic( | 6161 | const cross_2 = try cg.callIntrinsic( |
| 6123 | "__multi3", | 6162 | .__multi3, |
| 6124 | &[_]InternPool.Index{.i64_type} ** 4, | 6163 | &[_]InternPool.Index{.i64_type} ** 4, |
| 6125 | Type.i128, | 6164 | Type.i128, |
| 6126 | &.{ rhs_msb, zero, lhs_lsb, zero }, | 6165 | &.{ rhs_msb, zero, lhs_lsb, zero }, |
| 6127 | ); | 6166 | ); |
| 6128 | const mul_lsb = try cg.callIntrinsic( | 6167 | const mul_lsb = try cg.callIntrinsic( |
| 6129 | "__multi3", | 6168 | .__multi3, |
| 6130 | &[_]InternPool.Index{.i64_type} ** 4, | 6169 | &[_]InternPool.Index{.i64_type} ** 4, |
| 6131 | Type.i128, | 6170 | Type.i128, |
| 6132 | &.{ rhs_lsb, zero, lhs_lsb, zero }, | 6171 | &.{ rhs_lsb, zero, lhs_lsb, zero }, |
| ... | @@ -6165,7 +6204,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6165,7 +6204,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6165 | } else if (int_info.bits == 128 and int_info.signedness == .signed) blk: { | 6204 | } else if (int_info.bits == 128 and int_info.signedness == .signed) blk: { |
| 6166 | const overflow_ret = try cg.allocStack(Type.i32); | 6205 | const overflow_ret = try cg.allocStack(Type.i32); |
| 6167 | const res = try cg.callIntrinsic( | 6206 | const res = try cg.callIntrinsic( |
| 6168 | "__muloti4", | 6207 | .__muloti4, |
| 6169 | &[_]InternPool.Index{ .i128_type, .i128_type, .usize_type }, | 6208 | &[_]InternPool.Index{ .i128_type, .i128_type, .usize_type }, |
| 6170 | Type.i128, | 6209 | Type.i128, |
| 6171 | &.{ lhs, rhs, overflow_ret }, | 6210 | &.{ lhs, rhs, overflow_ret }, |
| ... | @@ -6185,8 +6224,12 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6185,8 +6224,12 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6185 | return cg.finishAir(inst, result, &.{ extra.lhs, extra.rhs }); | 6224 | return cg.finishAir(inst, result, &.{ extra.lhs, extra.rhs }); |
| 6186 | } | 6225 | } |
| 6187 | | 6226 | |
| 6188 | fn airMaxMin(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | 6227 | fn airMaxMin( |
| 6189 | assert(op == .max or op == .min); | 6228 | cg: *CodeGen, |
| | 6229 | inst: Air.Inst.Index, |
| | 6230 | op: enum { fmax, fmin }, |
| | 6231 | cmp_op: std.math.CompareOperator, |
| | 6232 | ) InnerError!void { |
| 6190 | const pt = cg.pt; | 6233 | const pt = cg.pt; |
| 6191 | const zcu = pt.zcu; | 6234 | const zcu = pt.zcu; |
| 6192 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6235 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | @@ -6204,20 +6247,22 @@ fn airMaxMin(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -6204,20 +6247,22 @@ fn airMaxMin(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 6204 | const rhs = try cg.resolveInst(bin_op.rhs); | 6247 | const rhs = try cg.resolveInst(bin_op.rhs); |
| 6205 | | 6248 | |
| 6206 | if (ty.zigTypeTag(zcu) == .float) { | 6249 | if (ty.zigTypeTag(zcu) == .float) { |
| 6207 | var fn_name_buf: [64]u8 = undefined; | 6250 | const intrinsic = switch (op) { |
| 6208 | const float_bits = ty.floatBits(cg.target.*); | 6251 | inline .fmin, .fmax => |ct_op| switch (ty.floatBits(cg.target.*)) { |
| 6209 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "{s}f{s}{s}", .{ | 6252 | inline 16, 32, 64, 80, 128 => |bits| @field( |
| 6210 | target_util.libcFloatPrefix(float_bits), | 6253 | Mir.Intrinsic, |
| 6211 | @tagName(op), | 6254 | libcFloatPrefix(bits) ++ @tagName(ct_op) ++ libcFloatSuffix(bits), |
| 6212 | target_util.libcFloatSuffix(float_bits), | 6255 | ), |
| 6213 | }) catch unreachable; | 6256 | else => unreachable, |
| 6214 | const result = try cg.callIntrinsic(fn_name, &.{ ty.ip_index, ty.ip_index }, ty, &.{ lhs, rhs }); | 6257 | }, |
| | 6258 | }; |
| | 6259 | const result = try cg.callIntrinsic(intrinsic, &.{ ty.ip_index, ty.ip_index }, ty, &.{ lhs, rhs }); |
| 6215 | try cg.lowerToStack(result); | 6260 | try cg.lowerToStack(result); |
| 6216 | } else { | 6261 | } else { |
| 6217 | // operands to select from | 6262 | // operands to select from |
| 6218 | try cg.lowerToStack(lhs); | 6263 | try cg.lowerToStack(lhs); |
| 6219 | try cg.lowerToStack(rhs); | 6264 | try cg.lowerToStack(rhs); |
| 6220 | _ = try cg.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt); | 6265 | _ = try cg.cmp(lhs, rhs, ty, cmp_op); |
| 6221 | | 6266 | |
| 6222 | // based on the result from comparison, return operand 0 or 1. | 6267 | // based on the result from comparison, return operand 0 or 1. |
| 6223 | try cg.addTag(.select); | 6268 | try cg.addTag(.select); |
| ... | @@ -6247,7 +6292,7 @@ fn airMulAdd(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6247,7 +6292,7 @@ fn airMulAdd(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6247 | const addend_ext = try cg.fpext(addend, ty, Type.f32); | 6292 | const addend_ext = try cg.fpext(addend, ty, Type.f32); |
| 6248 | // call to compiler-rt `fn fmaf(f32, f32, f32) f32` | 6293 | // call to compiler-rt `fn fmaf(f32, f32, f32) f32` |
| 6249 | const result = try cg.callIntrinsic( | 6294 | const result = try cg.callIntrinsic( |
| 6250 | "fmaf", | 6295 | .fmaf, |
| 6251 | &.{ .f32_type, .f32_type, .f32_type }, | 6296 | &.{ .f32_type, .f32_type, .f32_type }, |
| 6252 | Type.f32, | 6297 | Type.f32, |
| 6253 | &.{ rhs_ext, lhs_ext, addend_ext }, | 6298 | &.{ rhs_ext, lhs_ext, addend_ext }, |
| ... | @@ -6508,7 +6553,7 @@ fn airByteSwap(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6508,7 +6553,7 @@ fn airByteSwap(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6508 | switch (wasm_bits) { | 6553 | switch (wasm_bits) { |
| 6509 | 32 => { | 6554 | 32 => { |
| 6510 | const intrin_ret = try cg.callIntrinsic( | 6555 | const intrin_ret = try cg.callIntrinsic( |
| 6511 | "__bswapsi2", | 6556 | .__bswapsi2, |
| 6512 | &.{.u32_type}, | 6557 | &.{.u32_type}, |
| 6513 | Type.u32, | 6558 | Type.u32, |
| 6514 | &.{operand}, | 6559 | &.{operand}, |
| ... | @@ -6520,7 +6565,7 @@ fn airByteSwap(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6520,7 +6565,7 @@ fn airByteSwap(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6520 | }, | 6565 | }, |
| 6521 | 64 => { | 6566 | 64 => { |
| 6522 | const intrin_ret = try cg.callIntrinsic( | 6567 | const intrin_ret = try cg.callIntrinsic( |
| 6523 | "__bswapdi2", | 6568 | .__bswapdi2, |
| 6524 | &.{.u64_type}, | 6569 | &.{.u64_type}, |
| 6525 | Type.u64, | 6570 | Type.u64, |
| 6526 | &.{operand}, | 6571 | &.{operand}, |
| ... | @@ -6777,7 +6822,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6777,7 +6822,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6777 | } | 6822 | } |
| 6778 | const overflow_ret = try cg.allocStack(Type.i32); | 6823 | const overflow_ret = try cg.allocStack(Type.i32); |
| 6779 | _ = try cg.callIntrinsic( | 6824 | _ = try cg.callIntrinsic( |
| 6780 | "__mulodi4", | 6825 | .__mulodi4, |
| 6781 | &[_]InternPool.Index{ .i64_type, .i64_type, .usize_type }, | 6826 | &[_]InternPool.Index{ .i64_type, .i64_type, .usize_type }, |
| 6782 | Type.i64, | 6827 | Type.i64, |
| 6783 | &.{ lhs, rhs, overflow_ret }, | 6828 | &.{ lhs, rhs, overflow_ret }, |
| ... | @@ -6795,7 +6840,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6795,7 +6840,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6795 | } | 6840 | } |
| 6796 | const overflow_ret = try cg.allocStack(Type.i32); | 6841 | const overflow_ret = try cg.allocStack(Type.i32); |
| 6797 | const ret = try cg.callIntrinsic( | 6842 | const ret = try cg.callIntrinsic( |
| 6798 | "__muloti4", | 6843 | .__muloti4, |
| 6799 | &[_]InternPool.Index{ .i128_type, .i128_type, .usize_type }, | 6844 | &[_]InternPool.Index{ .i128_type, .i128_type, .usize_type }, |
| 6800 | Type.i128, | 6845 | Type.i128, |
| 6801 | &.{ lhs, rhs, overflow_ret }, | 6846 | &.{ lhs, rhs, overflow_ret }, |
| ... | @@ -7044,17 +7089,14 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7044,17 +7089,14 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7044 | /// May leave the return value on the stack. | 7089 | /// May leave the return value on the stack. |
| 7045 | fn callIntrinsic( | 7090 | fn callIntrinsic( |
| 7046 | cg: *CodeGen, | 7091 | cg: *CodeGen, |
| 7047 | name: []const u8, | 7092 | intrinsic: Mir.Intrinsic, |
| 7048 | param_types: []const InternPool.Index, | 7093 | param_types: []const InternPool.Index, |
| 7049 | return_type: Type, | 7094 | return_type: Type, |
| 7050 | args: []const WValue, | 7095 | args: []const WValue, |
| 7051 | ) InnerError!WValue { | 7096 | ) InnerError!WValue { |
| 7052 | assert(param_types.len == args.len); | 7097 | assert(param_types.len == args.len); |
| 7053 | const wasm = cg.wasm; | | |
| 7054 | const pt = cg.pt; | 7098 | const pt = cg.pt; |
| 7055 | const zcu = pt.zcu; | 7099 | const zcu = pt.zcu; |
| 7056 | const func_type_index = try genFunctype(wasm, .{ .wasm_watc = .{} }, param_types, return_type, pt, cg.target); | | |
| 7057 | const func_index = wasm.getOutputFunction(try wasm.internString(name), func_type_index); | | |
| 7058 | | 7100 | |
| 7059 | // Always pass over C-ABI | 7101 | // Always pass over C-ABI |
| 7060 | | 7102 | |
| ... | @@ -7074,8 +7116,7 @@ fn callIntrinsic( | ... | @@ -7074,8 +7116,7 @@ fn callIntrinsic( |
| 7074 | try cg.lowerArg(.{ .wasm_watc = .{} }, Type.fromInterned(param_types[arg_i]), arg); | 7116 | try cg.lowerArg(.{ .wasm_watc = .{} }, Type.fromInterned(param_types[arg_i]), arg); |
| 7075 | } | 7117 | } |
| 7076 | | 7118 | |
| 7077 | // Actually call our intrinsic | 7119 | try cg.addInst(.{ .tag = .call_intrinsic, .data = .{ .intrinsic = intrinsic } }); |
| 7078 | try cg.addLabel(.call_func, func_index); | | |
| 7079 | | 7120 | |
| 7080 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { | 7121 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 7081 | return .none; | 7122 | return .none; |
| ... | @@ -7097,7 +7138,7 @@ fn airTagName(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7097,7 +7138,7 @@ fn airTagName(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7097 | const result_ptr = try cg.allocStack(cg.typeOfIndex(inst)); | 7138 | const result_ptr = try cg.allocStack(cg.typeOfIndex(inst)); |
| 7098 | try cg.lowerToStack(result_ptr); | 7139 | try cg.lowerToStack(result_ptr); |
| 7099 | try cg.emitWValue(operand); | 7140 | try cg.emitWValue(operand); |
| 7100 | try cg.addIpIndex(.call_tag_name, enum_ty.toIntern()); | 7141 | try cg.addInst(.{ .tag = .call_tag_name, .data = .{ .ip_index = enum_ty.toIntern() } }); |
| 7101 | | 7142 | |
| 7102 | return cg.finishAir(inst, result_ptr, &.{un_op}); | 7143 | return cg.finishAir(inst, result_ptr, &.{un_op}); |
| 7103 | } | 7144 | } |
| ... | @@ -7514,3 +7555,38 @@ fn typeOfIndex(cg: *CodeGen, inst: Air.Inst.Index) Type { | ... | @@ -7514,3 +7555,38 @@ fn typeOfIndex(cg: *CodeGen, inst: Air.Inst.Index) Type { |
| 7514 | const zcu = pt.zcu; | 7555 | const zcu = pt.zcu; |
| 7515 | return cg.air.typeOfIndex(inst, &zcu.intern_pool); | 7556 | return cg.air.typeOfIndex(inst, &zcu.intern_pool); |
| 7516 | } | 7557 | } |
| | 7558 | |
| | 7559 | fn floatCmpIntrinsic(op: std.math.CompareOperator, bits: u16) Mir.Intrinsic { |
| | 7560 | return switch (op) { |
| | 7561 | .lt => switch (bits) { |
| | 7562 | 80 => .__ltxf2, |
| | 7563 | 128 => .__lttf2, |
| | 7564 | else => unreachable, |
| | 7565 | }, |
| | 7566 | .lte => switch (bits) { |
| | 7567 | 80 => .__lexf2, |
| | 7568 | 128 => .__letf2, |
| | 7569 | else => unreachable, |
| | 7570 | }, |
| | 7571 | .eq => switch (bits) { |
| | 7572 | 80 => .__eqxf2, |
| | 7573 | 128 => .__eqtf2, |
| | 7574 | else => unreachable, |
| | 7575 | }, |
| | 7576 | .neq => switch (bits) { |
| | 7577 | 80 => .__nexf2, |
| | 7578 | 128 => .__netf2, |
| | 7579 | else => unreachable, |
| | 7580 | }, |
| | 7581 | .gte => switch (bits) { |
| | 7582 | 80 => .__gexf2, |
| | 7583 | 128 => .__getf2, |
| | 7584 | else => unreachable, |
| | 7585 | }, |
| | 7586 | .gt => switch (bits) { |
| | 7587 | 80 => .__gtxf2, |
| | 7588 | 128 => .__gttf2, |
| | 7589 | else => unreachable, |
| | 7590 | }, |
| | 7591 | }; |
| | 7592 | } |