| ... | @@ -992,13 +992,12 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 | ... | @@ -992,13 +992,12 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 |
| 992 | fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { | 992 | fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { |
| 993 | const target = mod.getTarget(); | 993 | const target = mod.getTarget(); |
| 994 | return switch (ty.zigTypeTag(mod)) { | 994 | return switch (ty.zigTypeTag(mod)) { |
| 995 | .Float => blk: { | 995 | .Float => switch (ty.floatBits(target)) { |
| 996 | const bits = ty.floatBits(target); | 996 | 16 => wasm.Valtype.i32, // stored/loaded as u16 |
| 997 | if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16 | 997 | 32 => wasm.Valtype.f32, |
| 998 | if (bits == 32) break :blk wasm.Valtype.f32; | 998 | 64 => wasm.Valtype.f64, |
| 999 | if (bits == 64) break :blk wasm.Valtype.f64; | 999 | 80, 128 => wasm.Valtype.i64, |
| 1000 | if (bits == 128) break :blk wasm.Valtype.i64; | 1000 | else => unreachable, |
| 1001 | return wasm.Valtype.i32; // represented as pointer to stack | | |
| 1002 | }, | 1001 | }, |
| 1003 | .Int, .Enum => blk: { | 1002 | .Int, .Enum => blk: { |
| 1004 | const info = ty.intInfo(mod); | 1003 | const info = ty.intInfo(mod); |
| ... | @@ -2795,6 +2794,11 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In | ... | @@ -2795,6 +2794,11 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2795 | } | 2794 | } |
| 2796 | | 2795 | |
| 2797 | const float_bits = ty.floatBits(func.target); | 2796 | const float_bits = ty.floatBits(func.target); |
| | 2797 | |
| | 2798 | if (float_op == .neg) { |
| | 2799 | return func.floatNeg(ty, args[0]); |
| | 2800 | } |
| | 2801 | |
| 2798 | if (float_bits == 32 or float_bits == 64) { | 2802 | if (float_bits == 32 or float_bits == 64) { |
| 2799 | if (float_op.toOp()) |op| { | 2803 | if (float_op.toOp()) |op| { |
| 2800 | for (args) |operand| { | 2804 | for (args) |operand| { |
| ... | @@ -2804,13 +2808,6 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In | ... | @@ -2804,13 +2808,6 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2804 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 2808 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 2805 | return .stack; | 2809 | return .stack; |
| 2806 | } | 2810 | } |
| 2807 | } else if (float_bits == 16 and float_op == .neg) { | | |
| 2808 | try func.emitWValue(args[0]); | | |
| 2809 | try func.addImm32(std.math.minInt(i16)); | | |
| 2810 | try func.addTag(Mir.Inst.Tag.fromOpcode(.i32_xor)); | | |
| 2811 | return .stack; | | |
| 2812 | } else if (float_bits == 128 and float_op == .neg) { | | |
| 2813 | return func.fail("TODO: Implement neg for f128", .{}); | | |
| 2814 | } | 2811 | } |
| 2815 | | 2812 | |
| 2816 | var fn_name_buf: [64]u8 = undefined; | 2813 | var fn_name_buf: [64]u8 = undefined; |
| ... | @@ -2853,6 +2850,49 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In | ... | @@ -2853,6 +2850,49 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2853 | return func.callIntrinsic(fn_name, param_types, ty, args); | 2850 | return func.callIntrinsic(fn_name, param_types, ty, args); |
| 2854 | } | 2851 | } |
| 2855 | | 2852 | |
| | 2853 | /// NOTE: The result value remains on top of the stack. |
| | 2854 | fn floatNeg(func: *CodeGen, ty: Type, arg: WValue) InnerError!WValue { |
| | 2855 | const float_bits = ty.floatBits(func.target); |
| | 2856 | switch (float_bits) { |
| | 2857 | 16 => { |
| | 2858 | try func.emitWValue(arg); |
| | 2859 | try func.addImm32(std.math.minInt(i16)); |
| | 2860 | try func.addTag(.i32_xor); |
| | 2861 | return .stack; |
| | 2862 | }, |
| | 2863 | 32, 64 => { |
| | 2864 | try func.emitWValue(arg); |
| | 2865 | const val_type: wasm.Valtype = if (float_bits == 32) .f32 else .f64; |
| | 2866 | const opcode = buildOpcode(.{ .op = .neg, .valtype1 = val_type }); |
| | 2867 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| | 2868 | return .stack; |
| | 2869 | }, |
| | 2870 | 80, 128 => { |
| | 2871 | const result = try func.allocStack(ty); |
| | 2872 | try func.emitWValue(result); |
| | 2873 | try func.emitWValue(arg); |
| | 2874 | try func.addMemArg(.i64_load, .{ .offset = 0 + arg.offset(), .alignment = 2 }); |
| | 2875 | try func.addMemArg(.i64_store, .{ .offset = 0 + result.offset(), .alignment = 2 }); |
| | 2876 | |
| | 2877 | try func.emitWValue(result); |
| | 2878 | try func.emitWValue(arg); |
| | 2879 | try func.addMemArg(.i64_load, .{ .offset = 8 + arg.offset(), .alignment = 2 }); |
| | 2880 | |
| | 2881 | if (float_bits == 80) { |
| | 2882 | try func.addImm64(0x8000); |
| | 2883 | try func.addTag(.i64_xor); |
| | 2884 | try func.addMemArg(.i64_store16, .{ .offset = 8 + result.offset(), .alignment = 2 }); |
| | 2885 | } else { |
| | 2886 | try func.addImm64(0x8000000000000000); |
| | 2887 | try func.addTag(.i64_xor); |
| | 2888 | try func.addMemArg(.i64_store, .{ .offset = 8 + result.offset(), .alignment = 2 }); |
| | 2889 | } |
| | 2890 | return result; |
| | 2891 | }, |
| | 2892 | else => unreachable, |
| | 2893 | } |
| | 2894 | } |
| | 2895 | |
| 2856 | fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | 2896 | fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2857 | const mod = func.bin_file.base.options.module.?; | 2897 | const mod = func.bin_file.base.options.module.?; |
| 2858 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 2898 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |