authorgravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2023-09-08 01:19:38+02:00
committergravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2023-09-10 15:59:02+02:00
log9d6b6bddb60e5a970b1c849c2a0b7a66451f8bc3
tree8a94a2bb772e8b03fa58d7a2af381aa4f12f3ddd
parent55694c2a4df8d11f5197b57393b0c64664d045b9

wasm: implement common conversions between integers/floats with bitsize larger than 64 bits


1 files changed, 48 insertions(+), 8 deletions(-)

src/arch/wasm/CodeGen.zig+48-8
...@@ -4857,11 +4857,31 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4857,11 +4857,31 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4857 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4857 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
48584858
4859 const operand = try func.resolveInst(ty_op.operand);4859 const operand = try func.resolveInst(ty_op.operand);
4860 const dest_ty = func.typeOfIndex(inst);
4861 const op_ty = func.typeOf(ty_op.operand);4860 const op_ty = func.typeOf(ty_op.operand);
4861 const op_bits = op_ty.floatBits(func.target);
4862
4863 const dest_ty = func.typeOfIndex(inst);
4864 const dest_info = dest_ty.intInfo(mod);
4865
4866 if (dest_info.bits > 128) {
4867 return func.fail("TODO: intFromFloat for integers/floats with bitsize {}", .{dest_info.bits});
4868 }
4869
4870 if ((op_bits != 32 and op_bits != 64) or dest_info.bits > 64) {
4871 const dest_bitsize = if (dest_info.bits <= 16) 16 else std.math.ceilPowerOfTwoAssert(u16, dest_info.bits);
4872
4873 var fn_name_buf: [16]u8 = undefined;
4874 const fn_name = std.fmt.bufPrint(&fn_name_buf, "__fix{s}{s}f{s}i", .{
4875 switch (dest_info.signedness) {
4876 .signed => "",
4877 .unsigned => "uns",
4878 },
4879 target_util.compilerRtFloatAbbrev(op_bits),
4880 target_util.compilerRtIntAbbrev(dest_bitsize),
4881 }) catch unreachable;
48624882
4863 if (op_ty.abiSize(mod) > 8) {4883 const result = try (try func.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand})).toLocal(func, dest_ty);
4864 return func.fail("TODO: intFromFloat for integers/floats with bitsize larger than 64 bits", .{});4884 return func.finishAir(inst, result, &.{ty_op.operand});
4865 }4885 }
48664886
4867 try func.emitWValue(operand);4887 try func.emitWValue(operand);
...@@ -4869,7 +4889,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4869,7 +4889,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4869 .op = .trunc,4889 .op = .trunc,
4870 .valtype1 = typeToValtype(dest_ty, mod),4890 .valtype1 = typeToValtype(dest_ty, mod),
4871 .valtype2 = typeToValtype(op_ty, mod),4891 .valtype2 = typeToValtype(op_ty, mod),
4872 .signedness = if (dest_ty.isSignedInt(mod)) .signed else .unsigned,4892 .signedness = dest_info.signedness,
4873 });4893 });
4874 try func.addTag(Mir.Inst.Tag.fromOpcode(op));4894 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
4875 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);4895 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);
...@@ -4882,11 +4902,31 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4882,11 +4902,31 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4882 const ty_op = func.air.instructions.items(.data)[inst].ty_op;4902 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
48834903
4884 const operand = try func.resolveInst(ty_op.operand);4904 const operand = try func.resolveInst(ty_op.operand);
4885 const dest_ty = func.typeOfIndex(inst);
4886 const op_ty = func.typeOf(ty_op.operand);4905 const op_ty = func.typeOf(ty_op.operand);
4906 const op_info = op_ty.intInfo(mod);
4907
4908 const dest_ty = func.typeOfIndex(inst);
4909 const dest_bits = dest_ty.floatBits(func.target);
4910
4911 if (op_info.bits > 128) {
4912 return func.fail("TODO: floatFromInt for integers/floats with bitsize {d} bits", .{op_info.bits});
4913 }
4914
4915 if (op_info.bits > 64 or (dest_bits > 64 or dest_bits < 32)) {
4916 const op_bitsize = if (op_info.bits <= 16) 16 else std.math.ceilPowerOfTwoAssert(u16, op_info.bits);
4917
4918 var fn_name_buf: [16]u8 = undefined;
4919 const fn_name = std.fmt.bufPrint(&fn_name_buf, "__float{s}{s}i{s}f", .{
4920 switch (op_info.signedness) {
4921 .signed => "",
4922 .unsigned => "un",
4923 },
4924 target_util.compilerRtIntAbbrev(op_bitsize),
4925 target_util.compilerRtFloatAbbrev(dest_bits),
4926 }) catch unreachable;
48874927
4888 if (op_ty.abiSize(mod) > 8) {4928 const result = try (try func.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand})).toLocal(func, dest_ty);
4889 return func.fail("TODO: floatFromInt for integers/floats with bitsize larger than 64 bits", .{});4929 return func.finishAir(inst, result, &.{ty_op.operand});
4890 }4930 }
48914931
4892 try func.emitWValue(operand);4932 try func.emitWValue(operand);
...@@ -4894,7 +4934,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4894,7 +4934,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4894 .op = .convert,4934 .op = .convert,
4895 .valtype1 = typeToValtype(dest_ty, mod),4935 .valtype1 = typeToValtype(dest_ty, mod),
4896 .valtype2 = typeToValtype(op_ty, mod),4936 .valtype2 = typeToValtype(op_ty, mod),
4897 .signedness = if (op_ty.isSignedInt(mod)) .signed else .unsigned,4937 .signedness = op_info.signedness,
4898 });4938 });
4899 try func.addTag(Mir.Inst.Tag.fromOpcode(op));4939 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
49004940