| ... | @@ -112,11 +112,7 @@ const ValueRenderLocation = enum { | ... | @@ -112,11 +112,7 @@ const ValueRenderLocation = enum { |
| 112 | } | 112 | } |
| 113 | }; | 113 | }; |
| 114 | | 114 | |
| 115 | const BuiltinInfo = enum { | 115 | const BuiltinInfo = enum { none, bits }; |
| 116 | None, | | |
| 117 | Range, | | |
| 118 | Bits, | | |
| 119 | }; | | |
| 120 | | 116 | |
| 121 | const reserved_idents = std.ComptimeStringMap(void, .{ | 117 | const reserved_idents = std.ComptimeStringMap(void, .{ |
| 122 | // C language | 118 | // C language |
| ... | @@ -440,6 +436,10 @@ pub const Function = struct { | ... | @@ -440,6 +436,10 @@ pub const Function = struct { |
| 440 | return f.object.dg.typeToCType(ty, kind); | 436 | return f.object.dg.typeToCType(ty, kind); |
| 441 | } | 437 | } |
| 442 | | 438 | |
| | 439 | fn byteSize(f: *Function, cty: CType) u64 { |
| | 440 | return f.object.dg.byteSize(cty); |
| | 441 | } |
| | 442 | |
| 443 | fn renderType(f: *Function, w: anytype, t: Type) !void { | 443 | fn renderType(f: *Function, w: anytype, t: Type) !void { |
| 444 | return f.object.dg.renderType(w, t); | 444 | return f.object.dg.renderType(w, t); |
| 445 | } | 445 | } |
| ... | @@ -1003,8 +1003,9 @@ pub const DeclGen = struct { | ... | @@ -1003,8 +1003,9 @@ pub const DeclGen = struct { |
| 1003 | // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); | 1003 | // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); |
| 1004 | } | 1004 | } |
| 1005 | | 1005 | |
| 1006 | try writer.writeAll("zig_make_special_"); | 1006 | try writer.writeAll("zig_"); |
| 1007 | if (location == .StaticInitializer) try writer.writeAll("constant_"); | 1007 | try writer.writeAll(if (location == .StaticInitializer) "init" else "make"); |
| | 1008 | try writer.writeAll("_special_"); |
| 1008 | try dg.renderTypeForBuiltinFnName(writer, ty); | 1009 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 1009 | try writer.writeByte('('); | 1010 | try writer.writeByte('('); |
| 1010 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); | 1011 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); |
| ... | @@ -1565,6 +1566,10 @@ pub const DeclGen = struct { | ... | @@ -1565,6 +1566,10 @@ pub const DeclGen = struct { |
| 1565 | return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); | 1566 | return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); |
| 1566 | } | 1567 | } |
| 1567 | | 1568 | |
| | 1569 | fn byteSize(dg: *DeclGen, cty: CType) u64 { |
| | 1570 | return cty.byteSize(dg.ctypes.set, dg.module.getTarget()); |
| | 1571 | } |
| | 1572 | |
| 1568 | /// Renders a type as a single identifier, generating intermediate typedefs | 1573 | /// Renders a type as a single identifier, generating intermediate typedefs |
| 1569 | /// if necessary. | 1574 | /// if necessary. |
| 1570 | /// | 1575 | /// |
| ... | @@ -1861,51 +1866,64 @@ pub const DeclGen = struct { | ... | @@ -1861,51 +1866,64 @@ pub const DeclGen = struct { |
| 1861 | } | 1866 | } |
| 1862 | | 1867 | |
| 1863 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { | 1868 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { |
| 1864 | const target = dg.module.getTarget(); | 1869 | try dg.renderCTypeForBuiltinFnName(writer, try dg.typeToCType(ty, .complete)); |
| 1865 | if (ty.isAbiInt()) { | 1870 | } |
| 1866 | const int_info = ty.intInfo(target); | 1871 | |
| 1867 | const c_bits = toCIntBits(int_info.bits) orelse | 1872 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, cty: CType) !void { |
| 1868 | return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | 1873 | switch (cty.tag()) { |
| 1869 | try writer.print("{c}{d}", .{ signAbbrev(int_info.signedness), c_bits }); | 1874 | else => try writer.print("{c}{d}", .{ |
| 1870 | } else if (ty.isRuntimeFloat()) { | 1875 | if (cty.isBool()) |
| 1871 | try ty.print(writer, dg.module); | 1876 | signAbbrev(.unsigned) |
| 1872 | } else if (ty.isPtrAtRuntime()) { | 1877 | else if (cty.isInteger()) |
| 1873 | try writer.print("p{d}", .{ty.bitSize(target)}); | 1878 | signAbbrev(cty.signedness() orelse .unsigned) |
| 1874 | } else if (ty.zigTypeTag() == .Bool) { | 1879 | else if (cty.isFloat()) |
| 1875 | try writer.print("u8", .{}); | 1880 | @as(u8, 'f') |
| 1876 | } else return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ | 1881 | else if (cty.isPointer()) |
| 1877 | ty.fmt(dg.module), | 1882 | @as(u8, 'p') |
| 1878 | }); | 1883 | else |
| | 1884 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ |
| | 1885 | cty.tag(), |
| | 1886 | }), |
| | 1887 | if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8, |
| | 1888 | }), |
| | 1889 | .array => try writer.writeAll("big"), |
| | 1890 | .vector => try writer.writeAll("vec"), |
| | 1891 | } |
| 1879 | } | 1892 | } |
| 1880 | | 1893 | |
| 1881 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { | 1894 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { |
| 1882 | const target = dg.module.getTarget(); | | |
| 1883 | switch (info) { | 1895 | switch (info) { |
| 1884 | .None => {}, | 1896 | .none => {}, |
| 1885 | .Range => { | 1897 | .bits => { |
| 1886 | var arena = std.heap.ArenaAllocator.init(dg.gpa); | 1898 | const cty = try dg.typeToCType(ty, .complete); |
| 1887 | defer arena.deinit(); | 1899 | if (cty.castTag(.vector)) |pl| { |
| 1888 | | 1900 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = pl.data.len }; |
| 1889 | const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 }; | 1901 | try writer.print(", {}", .{try dg.fmtIntLiteral( |
| 1890 | var stack align(@alignOf(ExpectedContents)) = | 1902 | Type.u32, |
| 1891 | std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator()); | 1903 | Value.initPayload(&len_pl.base), |
| 1892 | | 1904 | .FunctionArgument, |
| 1893 | const int_info = ty.intInfo(target); | 1905 | )}); |
| 1894 | if (int_info.signedness == .signed) { | | |
| 1895 | const min_val = try ty.minInt(stack.get(), target); | | |
| 1896 | try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val, .Other)}); | | |
| 1897 | } | 1906 | } |
| 1898 | | 1907 | |
| 1899 | const max_val = try ty.maxInt(stack.get(), target); | 1908 | const target = dg.module.getTarget(); |
| 1900 | try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val, .Other)}); | 1909 | const elem_ty = ty.shallowElemType(); |
| 1901 | }, | 1910 | const elem_info = if (elem_ty.isAbiInt()) |
| 1902 | .Bits => { | 1911 | elem_ty.intInfo(target) |
| 1903 | var bits_pl = Value.Payload.U64{ | 1912 | else |
| 1904 | .base = .{ .tag = .int_u64 }, | 1913 | std.builtin.Type.Int{ |
| 1905 | .data = ty.bitSize(target), | 1914 | .signedness = .unsigned, |
| 1906 | }; | 1915 | .bits = @intCast(u16, elem_ty.bitSize(target)), |
| 1907 | const bits_val = Value.initPayload(&bits_pl.base); | 1916 | }; |
| 1908 | try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val, .Other)}); | 1917 | switch (cty.tag()) { |
| | 1918 | else => {}, |
| | 1919 | .array, .vector => try writer.print(", {}", .{elem_info.signedness == .signed}), |
| | 1920 | } |
| | 1921 | |
| | 1922 | var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = elem_info.bits }; |
| | 1923 | try writer.print(", {}", .{try dg.fmtIntLiteral(switch (cty.tag()) { |
| | 1924 | else => Type.u8, |
| | 1925 | .array, .vector => Type.u16, |
| | 1926 | }, Value.initPayload(&bits_pl.base), .FunctionArgument)}); |
| 1909 | }, | 1927 | }, |
| 1910 | } | 1928 | } |
| 1911 | } | 1929 | } |
| ... | @@ -2758,35 +2776,35 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2758,35 +2776,35 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2758 | | 2776 | |
| 2759 | // TODO use a different strategy for add, sub, mul, div | 2777 | // TODO use a different strategy for add, sub, mul, div |
| 2760 | // that communicates to the optimizer that wrapping is UB. | 2778 | // that communicates to the optimizer that wrapping is UB. |
| 2761 | .add => try airBinOp(f, inst, "+", "add", .None), | 2779 | .add => try airBinOp(f, inst, "+", "add", .none), |
| 2762 | .sub => try airBinOp(f, inst, "-", "sub", .None), | 2780 | .sub => try airBinOp(f, inst, "-", "sub", .none), |
| 2763 | .mul => try airBinOp(f, inst, "*", "mul", .None), | 2781 | .mul => try airBinOp(f, inst, "*", "mul", .none), |
| 2764 | | 2782 | |
| 2765 | .neg => try airFloatNeg(f, inst), | 2783 | .neg => try airFloatNeg(f, inst), |
| 2766 | .div_float => try airBinBuiltinCall(f, inst, "div", .None), | 2784 | .div_float => try airBinBuiltinCall(f, inst, "div", .none), |
| 2767 | | 2785 | |
| 2768 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None), | 2786 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), |
| 2769 | .rem => blk: { | 2787 | .rem => blk: { |
| 2770 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 2788 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 2771 | const lhs_ty = f.air.typeOf(bin_op.lhs); | 2789 | const lhs_ty = f.air.typeOf(bin_op.lhs); |
| 2772 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), | 2790 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), |
| 2773 | // so we only check one. | 2791 | // so we only check one. |
| 2774 | break :blk if (lhs_ty.isInt()) | 2792 | break :blk if (lhs_ty.isInt()) |
| 2775 | try airBinOp(f, inst, "%", "rem", .None) | 2793 | try airBinOp(f, inst, "%", "rem", .none) |
| 2776 | else | 2794 | else |
| 2777 | try airBinFloatOp(f, inst, "fmod"); | 2795 | try airBinFloatOp(f, inst, "fmod"); |
| 2778 | }, | 2796 | }, |
| 2779 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None), | 2797 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), |
| 2780 | .mod => try airBinBuiltinCall(f, inst, "mod", .None), | 2798 | .mod => try airBinBuiltinCall(f, inst, "mod", .none), |
| 2781 | | 2799 | |
| 2782 | .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits), | 2800 | .addwrap => try airBinBuiltinCall(f, inst, "addw", .bits), |
| 2783 | .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits), | 2801 | .subwrap => try airBinBuiltinCall(f, inst, "subw", .bits), |
| 2784 | .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits), | 2802 | .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .bits), |
| 2785 | | 2803 | |
| 2786 | .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits), | 2804 | .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits), |
| 2787 | .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits), | 2805 | .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits), |
| 2788 | .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits), | 2806 | .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits), |
| 2789 | .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits), | 2807 | .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits), |
| 2790 | | 2808 | |
| 2791 | .sqrt => try airUnFloatOp(f, inst, "sqrt"), | 2809 | .sqrt => try airUnFloatOp(f, inst, "sqrt"), |
| 2792 | .sin => try airUnFloatOp(f, inst, "sin"), | 2810 | .sin => try airUnFloatOp(f, inst, "sin"), |
| ... | @@ -2805,34 +2823,38 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2805,34 +2823,38 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2805 | | 2823 | |
| 2806 | .mul_add => try airMulAdd(f, inst), | 2824 | .mul_add => try airMulAdd(f, inst), |
| 2807 | | 2825 | |
| 2808 | .add_with_overflow => try airOverflow(f, inst, "add", .Bits), | 2826 | .add_with_overflow => try airOverflow(f, inst, "add", .bits), |
| 2809 | .sub_with_overflow => try airOverflow(f, inst, "sub", .Bits), | 2827 | .sub_with_overflow => try airOverflow(f, inst, "sub", .bits), |
| 2810 | .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits), | 2828 | .mul_with_overflow => try airOverflow(f, inst, "mul", .bits), |
| 2811 | .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits), | 2829 | .shl_with_overflow => try airOverflow(f, inst, "shl", .bits), |
| 2812 | | 2830 | |
| 2813 | .min => try airMinMax(f, inst, '<', "fmin"), | 2831 | .min => try airMinMax(f, inst, '<', "fmin"), |
| 2814 | .max => try airMinMax(f, inst, '>', "fmax"), | 2832 | .max => try airMinMax(f, inst, '>', "fmax"), |
| 2815 | | 2833 | |
| 2816 | .slice => try airSlice(f, inst), | 2834 | .slice => try airSlice(f, inst), |
| 2817 | | 2835 | |
| 2818 | .cmp_gt => try airCmpOp(f, inst, ">", "gt"), | 2836 | .cmp_gt => try airCmpOp(f, inst, .gt), |
| 2819 | .cmp_gte => try airCmpOp(f, inst, ">=", "ge"), | 2837 | .cmp_gte => try airCmpOp(f, inst, .gte), |
| 2820 | .cmp_lt => try airCmpOp(f, inst, "<", "lt"), | 2838 | .cmp_lt => try airCmpOp(f, inst, .lt), |
| 2821 | .cmp_lte => try airCmpOp(f, inst, "<=", "le"), | 2839 | .cmp_lte => try airCmpOp(f, inst, .lte), |
| 2822 | | 2840 | |
| 2823 | .cmp_eq => try airEquality(f, inst, "((", "==", "eq"), | 2841 | .cmp_eq => try airEquality(f, inst, .eq), |
| 2824 | .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"), | 2842 | .cmp_neq => try airEquality(f, inst, .neq), |
| 2825 | | 2843 | |
| 2826 | .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}), | 2844 | .cmp_vector => blk: { |
| | 2845 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| | 2846 | const extra = f.air.extraData(Air.VectorCmp, ty_pl.payload).data; |
| | 2847 | break :blk try cmpBuiltinCall(f, inst, extra, extra.compareOperator(), .operator, .bits); |
| | 2848 | }, |
| 2827 | .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst), | 2849 | .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst), |
| 2828 | | 2850 | |
| 2829 | // bool_and and bool_or are non-short-circuit operations | 2851 | // bool_and and bool_or are non-short-circuit operations |
| 2830 | .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None), | 2852 | .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .none), |
| 2831 | .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None), | 2853 | .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .none), |
| 2832 | .xor => try airBinOp(f, inst, "^", "xor", .None), | 2854 | .xor => try airBinOp(f, inst, "^", "xor", .none), |
| 2833 | .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None), | 2855 | .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .none), |
| 2834 | .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits), | 2856 | .shl, => try airBinBuiltinCall(f, inst, "shlw", .bits), |
| 2835 | .shl_exact => try airBinOp(f, inst, "<<", "shl", .None), | 2857 | .shl_exact => try airBinOp(f, inst, "<<", "shl", .none), |
| 2836 | .not => try airNot (f, inst), | 2858 | .not => try airNot (f, inst), |
| 2837 | | 2859 | |
| 2838 | .optional_payload => try airOptionalPayload(f, inst), | 2860 | .optional_payload => try airOptionalPayload(f, inst), |
| ... | @@ -2877,11 +2899,11 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2877,11 +2899,11 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2877 | .memcpy => try airMemcpy(f, inst), | 2899 | .memcpy => try airMemcpy(f, inst), |
| 2878 | .set_union_tag => try airSetUnionTag(f, inst), | 2900 | .set_union_tag => try airSetUnionTag(f, inst), |
| 2879 | .get_union_tag => try airGetUnionTag(f, inst), | 2901 | .get_union_tag => try airGetUnionTag(f, inst), |
| 2880 | .clz => try airUnBuiltinCall(f, inst, "clz", .Bits), | 2902 | .clz => try airUnBuiltinCall(f, inst, "clz", .bits), |
| 2881 | .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits), | 2903 | .ctz => try airUnBuiltinCall(f, inst, "ctz", .bits), |
| 2882 | .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits), | 2904 | .popcount => try airUnBuiltinCall(f, inst, "popcount", .bits), |
| 2883 | .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits), | 2905 | .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .bits), |
| 2884 | .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits), | 2906 | .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .bits), |
| 2885 | .tag_name => try airTagName(f, inst), | 2907 | .tag_name => try airTagName(f, inst), |
| 2886 | .error_name => try airErrorName(f, inst), | 2908 | .error_name => try airErrorName(f, inst), |
| 2887 | .splat => try airSplat(f, inst), | 2909 | .splat => try airSplat(f, inst), |
| ... | @@ -3349,7 +3371,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3349,7 +3371,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3349 | try f.writeCValueDeref(writer, operand); | 3371 | try f.writeCValueDeref(writer, operand); |
| 3350 | try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); | 3372 | try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); |
| 3351 | if (cant_cast) try writer.writeByte(')'); | 3373 | if (cant_cast) try writer.writeByte(')'); |
| 3352 | try f.object.dg.renderBuiltinInfo(writer, field_ty, .Bits); | 3374 | try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits); |
| 3353 | try writer.writeByte(')'); | 3375 | try writer.writeByte(')'); |
| 3354 | } else { | 3376 | } else { |
| 3355 | try f.writeCValue(writer, local, .Other); | 3377 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -3744,7 +3766,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3744,7 +3766,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3744 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { | 3766 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3745 | const inst_ty = f.air.typeOfIndex(inst); | 3767 | const inst_ty = f.air.typeOfIndex(inst); |
| 3746 | if (inst_ty.tag() != .bool) | 3768 | if (inst_ty.tag() != .bool) |
| 3747 | return try airUnBuiltinCall(f, inst, "not", .Bits); | 3769 | return try airUnBuiltinCall(f, inst, "not", .bits); |
| 3748 | | 3770 | |
| 3749 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3771 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3750 | | 3772 | |
| ... | @@ -3803,7 +3825,7 @@ fn airBinOp( | ... | @@ -3803,7 +3825,7 @@ fn airBinOp( |
| 3803 | return local; | 3825 | return local; |
| 3804 | } | 3826 | } |
| 3805 | | 3827 | |
| 3806 | fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue { | 3828 | fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: std.math.CompareOperator) !CValue { |
| 3807 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3829 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3808 | | 3830 | |
| 3809 | if (f.liveness.isUnused(inst)) { | 3831 | if (f.liveness.isUnused(inst)) { |
| ... | @@ -3813,10 +3835,11 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: | ... | @@ -3813,10 +3835,11 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: |
| 3813 | | 3835 | |
| 3814 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3836 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3815 | const target = f.object.dg.module.getTarget(); | 3837 | const target = f.object.dg.module.getTarget(); |
| 3816 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) | 3838 | const operand_bits = operand_ty.bitSize(target); |
| 3817 | return try cmpBuiltinCall(f, inst, operator, "cmp"); | 3839 | if (operand_ty.isInt() and operand_bits > 64) |
| | 3840 | return cmpBuiltinCall(f, inst, bin_op, operator, .cmp, if (operand_bits > 128) .bits else .none); |
| 3818 | if (operand_ty.isRuntimeFloat()) | 3841 | if (operand_ty.isRuntimeFloat()) |
| 3819 | return try cmpBuiltinCall(f, inst, operator, operation); | 3842 | return cmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); |
| 3820 | | 3843 | |
| 3821 | const inst_ty = f.air.typeOfIndex(inst); | 3844 | const inst_ty = f.air.typeOfIndex(inst); |
| 3822 | const lhs = try f.resolveInst(bin_op.lhs); | 3845 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -3829,7 +3852,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: | ... | @@ -3829,7 +3852,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: |
| 3829 | try writer.writeAll(" = "); | 3852 | try writer.writeAll(" = "); |
| 3830 | try f.writeCValue(writer, lhs, .Other); | 3853 | try f.writeCValue(writer, lhs, .Other); |
| 3831 | try writer.writeByte(' '); | 3854 | try writer.writeByte(' '); |
| 3832 | try writer.writeAll(operator); | 3855 | try writer.writeAll(compareOperatorC(operator)); |
| 3833 | try writer.writeByte(' '); | 3856 | try writer.writeByte(' '); |
| 3834 | try f.writeCValue(writer, rhs, .Other); | 3857 | try f.writeCValue(writer, rhs, .Other); |
| 3835 | try writer.writeAll(";\n"); | 3858 | try writer.writeAll(";\n"); |
| ... | @@ -3840,9 +3863,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: | ... | @@ -3840,9 +3863,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: |
| 3840 | fn airEquality( | 3863 | fn airEquality( |
| 3841 | f: *Function, | 3864 | f: *Function, |
| 3842 | inst: Air.Inst.Index, | 3865 | inst: Air.Inst.Index, |
| 3843 | negate_prefix: []const u8, | 3866 | operator: std.math.CompareOperator, |
| 3844 | operator: []const u8, | | |
| 3845 | operation: []const u8, | | |
| 3846 | ) !CValue { | 3867 | ) !CValue { |
| 3847 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3868 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3848 | | 3869 | |
| ... | @@ -3853,10 +3874,11 @@ fn airEquality( | ... | @@ -3853,10 +3874,11 @@ fn airEquality( |
| 3853 | | 3874 | |
| 3854 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3875 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3855 | const target = f.object.dg.module.getTarget(); | 3876 | const target = f.object.dg.module.getTarget(); |
| 3856 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) | 3877 | const operand_bits = operand_ty.bitSize(target); |
| 3857 | return try cmpBuiltinCall(f, inst, operator, "cmp"); | 3878 | if (operand_ty.isInt() and operand_bits > 64) |
| | 3879 | return cmpBuiltinCall(f, inst, bin_op, operator, .cmp, if (operand_bits > 128) .bits else .none); |
| 3858 | if (operand_ty.isRuntimeFloat()) | 3880 | if (operand_ty.isRuntimeFloat()) |
| 3859 | return try cmpBuiltinCall(f, inst, operator, operation); | 3881 | return cmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); |
| 3860 | | 3882 | |
| 3861 | const lhs = try f.resolveInst(bin_op.lhs); | 3883 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3862 | const rhs = try f.resolveInst(bin_op.rhs); | 3884 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3872,7 +3894,12 @@ fn airEquality( | ... | @@ -3872,7 +3894,12 @@ fn airEquality( |
| 3872 | // (A && B) || (C && (A == B)) | 3894 | // (A && B) || (C && (A == B)) |
| 3873 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload | 3895 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload |
| 3874 | | 3896 | |
| 3875 | try writer.writeAll(negate_prefix); | 3897 | switch (operator) { |
| | 3898 | .eq => {}, |
| | 3899 | .neq => try writer.writeByte('!'), |
| | 3900 | else => unreachable, |
| | 3901 | } |
| | 3902 | try writer.writeAll("(("); |
| 3876 | try f.writeCValue(writer, lhs, .Other); | 3903 | try f.writeCValue(writer, lhs, .Other); |
| 3877 | try writer.writeAll(".is_null && "); | 3904 | try writer.writeAll(".is_null && "); |
| 3878 | try f.writeCValue(writer, rhs, .Other); | 3905 | try f.writeCValue(writer, rhs, .Other); |
| ... | @@ -3891,7 +3918,7 @@ fn airEquality( | ... | @@ -3891,7 +3918,7 @@ fn airEquality( |
| 3891 | | 3918 | |
| 3892 | try f.writeCValue(writer, lhs, .Other); | 3919 | try f.writeCValue(writer, lhs, .Other); |
| 3893 | try writer.writeByte(' '); | 3920 | try writer.writeByte(' '); |
| 3894 | try writer.writeAll(operator); | 3921 | try writer.writeAll(compareOperatorC(operator)); |
| 3895 | try writer.writeByte(' '); | 3922 | try writer.writeByte(' '); |
| 3896 | try f.writeCValue(writer, rhs, .Other); | 3923 | try f.writeCValue(writer, rhs, .Other); |
| 3897 | try writer.writeAll(";\n"); | 3924 | try writer.writeAll(";\n"); |
| ... | @@ -3972,7 +3999,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons | ... | @@ -3972,7 +3999,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons |
| 3972 | const inst_ty = f.air.typeOfIndex(inst); | 3999 | const inst_ty = f.air.typeOfIndex(inst); |
| 3973 | const target = f.object.dg.module.getTarget(); | 4000 | const target = f.object.dg.module.getTarget(); |
| 3974 | if (inst_ty.isInt() and inst_ty.bitSize(target) > 64) | 4001 | if (inst_ty.isInt() and inst_ty.bitSize(target) > 64) |
| 3975 | return try airBinBuiltinCall(f, inst, operation[1..], .None); | 4002 | return try airBinBuiltinCall(f, inst, operation[1..], .none); |
| 3976 | if (inst_ty.isRuntimeFloat()) | 4003 | if (inst_ty.isRuntimeFloat()) |
| 3977 | return try airBinFloatOp(f, inst, operation); | 4004 | return try airBinFloatOp(f, inst, operation); |
| 3978 | | 4005 | |
| ... | @@ -4418,12 +4445,35 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4418,12 +4445,35 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4418 | | 4445 | |
| 4419 | // Ensure padding bits have the expected value. | 4446 | // Ensure padding bits have the expected value. |
| 4420 | if (dest_ty.isAbiInt()) { | 4447 | if (dest_ty.isAbiInt()) { |
| | 4448 | const dest_cty = try f.typeToCType(dest_ty, .complete); |
| | 4449 | const dest_info = dest_ty.intInfo(target); |
| | 4450 | var wrap_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) { |
| | 4451 | .unsigned => .int_unsigned, |
| | 4452 | .signed => .int_signed, |
| | 4453 | } }, .data = dest_info.bits }; |
| | 4454 | |
| 4421 | try f.writeCValue(writer, local, .Other); | 4455 | try f.writeCValue(writer, local, .Other); |
| | 4456 | if (dest_cty.castTag(.array)) |pl| { |
| | 4457 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { |
| | 4458 | .Little => pl.data.len - 1, |
| | 4459 | .Big => 0, |
| | 4460 | }}); |
| | 4461 | wrap_ty_pl.data -= 1; |
| | 4462 | wrap_ty_pl.data %= @intCast(u16, f.byteSize(f.indexToCType(pl.data.elem_type)) * 8); |
| | 4463 | wrap_ty_pl.data += 1; |
| | 4464 | } |
| | 4465 | const wrap_ty = Type.initPayload(&wrap_ty_pl.base); |
| 4422 | try writer.writeAll(" = zig_wrap_"); | 4466 | try writer.writeAll(" = zig_wrap_"); |
| 4423 | try f.object.dg.renderTypeForBuiltinFnName(writer, dest_ty); | 4467 | try f.object.dg.renderTypeForBuiltinFnName(writer, wrap_ty); |
| 4424 | try writer.writeByte('('); | 4468 | try writer.writeByte('('); |
| 4425 | try f.writeCValue(writer, local, .Other); | 4469 | try f.writeCValue(writer, local, .Other); |
| 4426 | try f.object.dg.renderBuiltinInfo(writer, dest_ty, .Bits); | 4470 | if (dest_cty.castTag(.array)) |pl| { |
| | 4471 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { |
| | 4472 | .Little => pl.data.len - 1, |
| | 4473 | .Big => 0, |
| | 4474 | }}); |
| | 4475 | } |
| | 4476 | try f.object.dg.renderBuiltinInfo(writer, wrap_ty, .bits); |
| 4427 | try writer.writeAll(");\n"); | 4477 | try writer.writeAll(");\n"); |
| 4428 | } | 4478 | } |
| 4429 | | 4479 | |
| ... | @@ -5438,7 +5488,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5438,7 +5488,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5438 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | 5488 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); |
| 5439 | try writer.writeByte(')'); | 5489 | try writer.writeByte(')'); |
| 5440 | if (cant_cast) try writer.writeByte(')'); | 5490 | if (cant_cast) try writer.writeByte(')'); |
| 5441 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .Bits); | 5491 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); |
| 5442 | try writer.writeAll(");\n"); | 5492 | try writer.writeAll(");\n"); |
| 5443 | if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; | 5493 | if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; |
| 5444 | | 5494 | |
| ... | @@ -5871,7 +5921,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5871,7 +5921,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5871 | try f.writeCValue(writer, operand, .FunctionArgument); | 5921 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 5872 | try writer.writeByte(')'); | 5922 | try writer.writeByte(')'); |
| 5873 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { | 5923 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { |
| 5874 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); | 5924 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); |
| 5875 | try writer.writeByte(')'); | 5925 | try writer.writeByte(')'); |
| 5876 | } | 5926 | } |
| 5877 | try writer.writeAll(";\n"); | 5927 | try writer.writeAll(";\n"); |
| ... | @@ -5972,29 +6022,46 @@ fn airBinBuiltinCall( | ... | @@ -5972,29 +6022,46 @@ fn airBinBuiltinCall( |
| 5972 | fn cmpBuiltinCall( | 6022 | fn cmpBuiltinCall( |
| 5973 | f: *Function, | 6023 | f: *Function, |
| 5974 | inst: Air.Inst.Index, | 6024 | inst: Air.Inst.Index, |
| 5975 | operator: []const u8, | 6025 | data: anytype, |
| 5976 | operation: []const u8, | 6026 | operator: std.math.CompareOperator, |
| | 6027 | operation: enum { cmp, operator }, |
| | 6028 | info: BuiltinInfo, |
| 5977 | ) !CValue { | 6029 | ) !CValue { |
| 5978 | const inst_ty = f.air.typeOfIndex(inst); | 6030 | const inst_ty = f.air.typeOfIndex(inst); |
| 5979 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 6031 | const operand_ty = f.air.typeOf(data.lhs); |
| 5980 | const operand_ty = f.air.typeOf(bin_op.lhs); | | |
| 5981 | | 6032 | |
| 5982 | const lhs = try f.resolveInst(bin_op.lhs); | 6033 | const lhs = try f.resolveInst(data.lhs); |
| 5983 | const rhs = try f.resolveInst(bin_op.rhs); | 6034 | const rhs = try f.resolveInst(data.rhs); |
| 5984 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6035 | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| | 6036 | |
| | 6037 | const ref_ret = inst_ty.tag() != .bool; |
| 5985 | | 6038 | |
| 5986 | const writer = f.object.writer(); | 6039 | const writer = f.object.writer(); |
| 5987 | const local = try f.allocLocal(inst, inst_ty); | 6040 | const local = try f.allocLocal(inst, inst_ty); |
| 5988 | try f.writeCValue(writer, local, .Other); | 6041 | if (!ref_ret) { |
| 5989 | try writer.writeAll(" = zig_"); | 6042 | try f.writeCValue(writer, local, .Other); |
| 5990 | try writer.writeAll(operation); | 6043 | try writer.writeAll(" = "); |
| 5991 | try writer.writeByte('_'); | 6044 | } |
| | 6045 | try writer.print("zig_{s}_", .{switch (operation) { |
| | 6046 | else => @tagName(operation), |
| | 6047 | .operator => compareOperatorAbbrev(operator), |
| | 6048 | }}); |
| 5992 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); | 6049 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 5993 | try writer.writeByte('('); | 6050 | try writer.writeByte('('); |
| | 6051 | if (ref_ret) { |
| | 6052 | try f.writeCValue(writer, local, .FunctionArgument); |
| | 6053 | try writer.writeAll(", "); |
| | 6054 | } |
| 5994 | try f.writeCValue(writer, lhs, .FunctionArgument); | 6055 | try f.writeCValue(writer, lhs, .FunctionArgument); |
| 5995 | try writer.writeAll(", "); | 6056 | try writer.writeAll(", "); |
| 5996 | try f.writeCValue(writer, rhs, .FunctionArgument); | 6057 | try f.writeCValue(writer, rhs, .FunctionArgument); |
| 5997 | try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) }); | 6058 | try f.object.dg.renderBuiltinInfo(writer, operand_ty, info); |
| | 6059 | try writer.writeByte(')'); |
| | 6060 | if (!ref_ret) try writer.print(" {s} {}", .{ |
| | 6061 | compareOperatorC(operator), |
| | 6062 | try f.fmtIntLiteral(Type.initTag(.i32), Value.zero), |
| | 6063 | }); |
| | 6064 | try writer.writeAll(";\n"); |
| 5998 | return local; | 6065 | return local; |
| 5999 | } | 6066 | } |
| 6000 | | 6067 | |
| ... | @@ -6675,7 +6742,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6675,7 +6742,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6675 | | 6742 | |
| 6676 | try writer.writeAll(", "); | 6743 | try writer.writeAll(", "); |
| 6677 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | 6744 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); |
| 6678 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); | 6745 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); |
| 6679 | try writer.writeByte(')'); | 6746 | try writer.writeByte(')'); |
| 6680 | if (!empty) try writer.writeByte(')'); | 6747 | if (!empty) try writer.writeByte(')'); |
| 6681 | | 6748 | |
| ... | @@ -7094,6 +7161,28 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { | ... | @@ -7094,6 +7161,28 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { |
| 7094 | } else unreachable; | 7161 | } else unreachable; |
| 7095 | } | 7162 | } |
| 7096 | | 7163 | |
| | 7164 | fn compareOperatorAbbrev(operator: std.math.CompareOperator) []const u8 { |
| | 7165 | return switch (operator) { |
| | 7166 | .lt => "lt", |
| | 7167 | .lte => "le", |
| | 7168 | .eq => "eq", |
| | 7169 | .gte => "ge", |
| | 7170 | .gt => "gt", |
| | 7171 | .neq => "ne", |
| | 7172 | }; |
| | 7173 | } |
| | 7174 | |
| | 7175 | fn compareOperatorC(operator: std.math.CompareOperator) []const u8 { |
| | 7176 | return switch (operator) { |
| | 7177 | .lt => "<", |
| | 7178 | .lte => "<=", |
| | 7179 | .eq => "==", |
| | 7180 | .gte => ">=", |
| | 7181 | .gt => ">", |
| | 7182 | .neq => "!=", |
| | 7183 | }; |
| | 7184 | } |
| | 7185 | |
| 7097 | fn StringLiteral(comptime WriterType: type) type { | 7186 | fn StringLiteral(comptime WriterType: type) type { |
| 7098 | // MSVC has a length limit of 16380 per string literal (before concatenation) | 7187 | // MSVC has a length limit of 16380 per string literal (before concatenation) |
| 7099 | const max_char_len = 4; | 7188 | const max_char_len = 4; |
| ... | @@ -7239,14 +7328,6 @@ fn formatIntLiteral( | ... | @@ -7239,14 +7328,6 @@ fn formatIntLiteral( |
| 7239 | .positive = undefined, | 7328 | .positive = undefined, |
| 7240 | }; | 7329 | }; |
| 7241 | defer allocator.free(wrap.limbs); | 7330 | defer allocator.free(wrap.limbs); |
| 7242 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or | | |
| 7243 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) | | |
| 7244 | return writer.print("{s}_{s}", .{ | | |
| 7245 | data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ | | |
| 7246 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, | | |
| 7247 | }), | | |
| 7248 | if (int.positive) "MAX" else "MIN", | | |
| 7249 | }); | | |
| 7250 | | 7331 | |
| 7251 | const c_limb_info: struct { | 7332 | const c_limb_info: struct { |
| 7252 | cty: CType, | 7333 | cty: CType, |
| ... | @@ -7277,6 +7358,15 @@ fn formatIntLiteral( | ... | @@ -7277,6 +7358,15 @@ fn formatIntLiteral( |
| 7277 | }, | 7358 | }, |
| 7278 | }; | 7359 | }; |
| 7279 | if (c_limb_info.count == 1) { | 7360 | if (c_limb_info.count == 1) { |
| | 7361 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| | 7362 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| | 7363 | return writer.print("{s}_{s}", .{ |
| | 7364 | data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ |
| | 7365 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| | 7366 | }), |
| | 7367 | if (int.positive) "MAX" else "MIN", |
| | 7368 | }); |
| | 7369 | |
| 7280 | if (!int.positive) try writer.writeByte('-'); | 7370 | if (!int.positive) try writer.writeByte('-'); |
| 7281 | try data.cty.renderLiteralPrefix(writer, data.kind); | 7371 | try data.cty.renderLiteralPrefix(writer, data.kind); |
| 7282 | | 7372 | |
| ... | @@ -7310,7 +7400,7 @@ fn formatIntLiteral( | ... | @@ -7310,7 +7400,7 @@ fn formatIntLiteral( |
| 7310 | try writer.writeAll(string); | 7400 | try writer.writeAll(string); |
| 7311 | } else { | 7401 | } else { |
| 7312 | try data.cty.renderLiteralPrefix(writer, data.kind); | 7402 | try data.cty.renderLiteralPrefix(writer, data.kind); |
| 7313 | wrap.convertToTwosComplement(int, .unsigned, data.int_info.bits); | 7403 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); |
| 7314 | std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); | 7404 | std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); |
| 7315 | wrap.len = wrap.limbs.len; | 7405 | wrap.len = wrap.limbs.len; |
| 7316 | const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); | 7406 | const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); |
| ... | @@ -7343,7 +7433,7 @@ fn formatIntLiteral( | ... | @@ -7343,7 +7433,7 @@ fn formatIntLiteral( |
| 7343 | c_limb_cty = c_limb_info.cty.toSigned(); | 7433 | c_limb_cty = c_limb_info.cty.toSigned(); |
| 7344 | | 7434 | |
| 7345 | c_limb_mut.positive = wrap.positive; | 7435 | c_limb_mut.positive = wrap.positive; |
| 7346 | c_limb_mut.convertToTwosComplement( | 7436 | c_limb_mut.truncate( |
| 7347 | c_limb_mut.toConst(), | 7437 | c_limb_mut.toConst(), |
| 7348 | .signed, | 7438 | .signed, |
| 7349 | data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), | 7439 | data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), |