| ... | @@ -19,6 +19,7 @@ const Liveness = @import("../Liveness.zig"); | ... | @@ -19,6 +19,7 @@ const Liveness = @import("../Liveness.zig"); |
| 19 | const CType = @import("../type.zig").CType; | 19 | const CType = @import("../type.zig").CType; |
| 20 | | 20 | |
| 21 | const Mutability = enum { Const, ConstArgument, Mut }; | 21 | const Mutability = enum { Const, ConstArgument, Mut }; |
| | 22 | const BigIntLimb = std.math.big.Limb; |
| 22 | const BigInt = std.math.big.int; | 23 | const BigInt = std.math.big.int; |
| 23 | | 24 | |
| 24 | pub const CValue = union(enum) { | 25 | pub const CValue = union(enum) { |
| ... | @@ -608,19 +609,25 @@ pub const DeclGen = struct { | ... | @@ -608,19 +609,25 @@ pub const DeclGen = struct { |
| 608 | .Bool => return dg.renderValue(writer, ty, Value.@"false", location), | 609 | .Bool => return dg.renderValue(writer, ty, Value.@"false", location), |
| 609 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}), | 610 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}), |
| 610 | .Float => { | 611 | .Float => { |
| | 612 | const bits = ty.floatBits(target); |
| | 613 | var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; |
| | 614 | const int_ty = Type.initPayload(&int_pl.base); |
| | 615 | |
| 611 | try writer.writeByte('('); | 616 | try writer.writeByte('('); |
| 612 | try dg.renderTypecast(writer, ty); | 617 | try dg.renderTypecast(writer, ty); |
| 613 | try writer.writeAll(")zig_suffix_"); | 618 | try writer.writeAll(")zig_as_"); |
| 614 | try dg.renderTypeForBuiltinFnName(writer, ty); | 619 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 615 | try writer.writeByte('('); | 620 | try writer.writeByte('('); |
| 616 | switch (ty.floatBits(target)) { | 621 | switch (bits) { |
| 617 | 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(u16))}), | 622 | 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(i16))}), |
| 618 | 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(u32))}), | 623 | 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(i32))}), |
| 619 | 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}), | 624 | 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(i64))}), |
| 620 | 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(u80))}), | 625 | 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(i80))}), |
| 621 | 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(u128))}), | 626 | 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(i128))}), |
| 622 | else => unreachable, | 627 | else => unreachable, |
| 623 | } | 628 | } |
| | 629 | try writer.writeAll(", "); |
| | 630 | try dg.renderValue(writer, int_ty, Value.undef, .FunctionArgument); |
| 624 | return writer.writeByte(')'); | 631 | return writer.writeByte(')'); |
| 625 | }, | 632 | }, |
| 626 | .Pointer => if (ty.isSlice()) { | 633 | .Pointer => if (ty.isSlice()) { |
| ... | @@ -770,21 +777,48 @@ pub const DeclGen = struct { | ... | @@ -770,21 +777,48 @@ pub const DeclGen = struct { |
| 770 | else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}), | 777 | else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}), |
| 771 | }, | 778 | }, |
| 772 | .Float => { | 779 | .Float => { |
| | 780 | const bits = ty.floatBits(target); |
| | 781 | const f128_val = val.toFloat(f128); |
| | 782 | |
| | 783 | var int_ty_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; |
| | 784 | const int_ty = Type.initPayload(&int_ty_pl.base); |
| | 785 | |
| | 786 | assert(bits <= 128); |
| | 787 | var int_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; |
| | 788 | var int_val_big = BigInt.Mutable{ |
| | 789 | .limbs = &int_val_limbs, |
| | 790 | .len = undefined, |
| | 791 | .positive = undefined, |
| | 792 | }; |
| | 793 | |
| | 794 | switch (bits) { |
| | 795 | 16 => int_val_big.set(@bitCast(i16, val.toFloat(f16))), |
| | 796 | 32 => int_val_big.set(@bitCast(i32, val.toFloat(f32))), |
| | 797 | 64 => int_val_big.set(@bitCast(i64, val.toFloat(f64))), |
| | 798 | 80 => int_val_big.set(@bitCast(i80, val.toFloat(f80))), |
| | 799 | 128 => int_val_big.set(@bitCast(i128, f128_val)), |
| | 800 | else => unreachable, |
| | 801 | } |
| | 802 | |
| | 803 | var int_val_pl = Value.Payload.BigInt{ |
| | 804 | .base = .{ .tag = if (int_val_big.positive) .int_big_positive else .int_big_negative }, |
| | 805 | .data = int_val_big.limbs[0..int_val_big.len], |
| | 806 | }; |
| | 807 | const int_val = Value.initPayload(&int_val_pl.base); |
| | 808 | |
| 773 | try writer.writeByte('('); | 809 | try writer.writeByte('('); |
| 774 | try dg.renderTypecast(writer, ty); | 810 | try dg.renderTypecast(writer, ty); |
| 775 | try writer.writeByte(')'); | 811 | try writer.writeByte(')'); |
| 776 | const f128_val = val.toFloat(f128); | | |
| 777 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); | | |
| 778 | if (std.math.isFinite(f128_val)) { | 812 | if (std.math.isFinite(f128_val)) { |
| 779 | try writer.writeAll("zig_suffix_"); | 813 | try writer.writeAll("zig_as_"); |
| 780 | try dg.renderTypeForBuiltinFnName(writer, ty); | 814 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 781 | try writer.writeByte('('); | 815 | try writer.writeByte('('); |
| 782 | switch (ty.floatBits(target)) { | 816 | switch (bits) { |
| 783 | 16 => try writer.print("{x}", .{@fabs(val.toFloat(f16))}), | 817 | 16 => try writer.print("{x}", .{val.toFloat(f16)}), |
| 784 | 32 => try writer.print("{x}", .{@fabs(val.toFloat(f32))}), | 818 | 32 => try writer.print("{x}", .{val.toFloat(f32)}), |
| 785 | 64 => try writer.print("{x}", .{@fabs(val.toFloat(f64))}), | 819 | 64 => try writer.print("{x}", .{val.toFloat(f64)}), |
| 786 | 80 => try writer.print("{x}", .{@fabs(val.toFloat(f80))}), | 820 | 80 => try writer.print("{x}", .{val.toFloat(f80)}), |
| 787 | 128 => try writer.print("{x}", .{@fabs(f128_val)}), | 821 | 128 => try writer.print("{x}", .{f128_val}), |
| 788 | else => unreachable, | 822 | else => unreachable, |
| 789 | } | 823 | } |
| 790 | } else { | 824 | } else { |
| ... | @@ -796,23 +830,26 @@ pub const DeclGen = struct { | ... | @@ -796,23 +830,26 @@ pub const DeclGen = struct { |
| 796 | "inf" | 830 | "inf" |
| 797 | else | 831 | else |
| 798 | unreachable; | 832 | unreachable; |
| 799 | try writer.writeAll("zig_builtin_constant_"); | 833 | |
| | 834 | try writer.writeAll("zig_as_special_"); |
| 800 | try dg.renderTypeForBuiltinFnName(writer, ty); | 835 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 801 | try writer.writeByte('('); | 836 | try writer.writeByte('('); |
| | 837 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); |
| | 838 | try writer.writeAll(", "); |
| 802 | try writer.writeAll(operation); | 839 | try writer.writeAll(operation); |
| 803 | try writer.writeAll(")("); | 840 | try writer.writeAll(", "); |
| 804 | if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) { | 841 | if (std.math.isNan(f128_val)) switch (bits) { |
| 805 | // We only actually need to pass the significand, but it will get | 842 | // We only actually need to pass the significand, but it will get |
| 806 | // properly masked anyway, so just pass the whole value. | 843 | // properly masked anyway, so just pass the whole value. |
| 807 | 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, @fabs(val.toFloat(f16)))}), | 844 | 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}), |
| 808 | 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, @fabs(val.toFloat(f32)))}), | 845 | 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}), |
| 809 | 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, @fabs(val.toFloat(f64)))}), | 846 | 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}), |
| 810 | 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, @fabs(val.toFloat(f80)))}), | 847 | 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}), |
| 811 | 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, @fabs(f128_val))}), | 848 | 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}), |
| 812 | else => unreachable, | 849 | else => unreachable, |
| 813 | }; | 850 | }; |
| 814 | } | 851 | } |
| 815 | return writer.writeByte(')'); | 852 | return writer.print(", {x})", .{try dg.fmtIntLiteral(int_ty, int_val)}); |
| 816 | }, | 853 | }, |
| 817 | .Pointer => switch (val.tag()) { | 854 | .Pointer => switch (val.tag()) { |
| 818 | .null_value, .zero => if (ty.isSlice()) { | 855 | .null_value, .zero => if (ty.isSlice()) { |
| ... | @@ -2299,11 +2336,14 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -2299,11 +2336,14 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2299 | | 2336 | |
| 2300 | // TODO use a different strategy for add, sub, mul, div | 2337 | // TODO use a different strategy for add, sub, mul, div |
| 2301 | // that communicates to the optimizer that wrapping is UB. | 2338 | // that communicates to the optimizer that wrapping is UB. |
| 2302 | .add => try airBinOp(f, inst, "+", "add", .None), | 2339 | .add => try airBinOp(f, inst, "+", "add", .None), |
| 2303 | .sub => try airBinOp(f, inst, "-", "sub", .None), | 2340 | .sub => try airBinOp(f, inst, "-", "sub", .None), |
| 2304 | .mul => try airBinOp(f, inst, "*", "mul", .None), | 2341 | .mul => try airBinOp(f, inst, "*", "mul", .None), |
| 2305 | .div_float, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None), | 2342 | |
| | 2343 | .neg => try airFloatNeg(f, inst), |
| | 2344 | .div_float => try airBinBuiltinCall(f, inst, "div", .None), |
| 2306 | | 2345 | |
| | 2346 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None), |
| 2307 | .rem => blk: { | 2347 | .rem => blk: { |
| 2308 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 2348 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 2309 | const lhs_ty = f.air.typeOf(bin_op.lhs); | 2349 | const lhs_ty = f.air.typeOf(bin_op.lhs); |
| ... | @@ -2314,16 +2354,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -2314,16 +2354,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2314 | else | 2354 | else |
| 2315 | try airBinFloatOp(f, inst, "fmod"); | 2355 | try airBinFloatOp(f, inst, "fmod"); |
| 2316 | }, | 2356 | }, |
| 2317 | .div_trunc => blk: { | | |
| 2318 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | | |
| 2319 | const lhs_ty = f.air.typeOf(bin_op.lhs); | | |
| 2320 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), | | |
| 2321 | // so we only check one. | | |
| 2322 | break :blk if (lhs_ty.isInt()) | | |
| 2323 | try airBinOp(f, inst, "/", "div_trunc", .None) | | |
| 2324 | else | | |
| 2325 | try airBinBuiltinCall(f, inst, "div_trunc", .None); | | |
| 2326 | }, | | |
| 2327 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None), | 2357 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None), |
| 2328 | .mod => try airBinBuiltinCall(f, inst, "mod", .None), | 2358 | .mod => try airBinBuiltinCall(f, inst, "mod", .None), |
| 2329 | | 2359 | |
| ... | @@ -2336,8 +2366,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -2336,8 +2366,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2336 | .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits), | 2366 | .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits), |
| 2337 | .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits), | 2367 | .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits), |
| 2338 | | 2368 | |
| 2339 | .neg => try airNeg(f, inst), | | |
| 2340 | | | |
| 2341 | .sqrt, | 2369 | .sqrt, |
| 2342 | .sin, | 2370 | .sin, |
| 2343 | .cos, | 2371 | .cos, |
| ... | @@ -2361,18 +2389,18 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -2361,18 +2389,18 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2361 | .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits), | 2389 | .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits), |
| 2362 | .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits), | 2390 | .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits), |
| 2363 | | 2391 | |
| 2364 | .min => try airMinMax(f, inst, '<'), | 2392 | .min => try airMinMax(f, inst, '<', "fmin"), |
| 2365 | .max => try airMinMax(f, inst, '>'), | 2393 | .max => try airMinMax(f, inst, '>', "fmax"), |
| 2366 | | 2394 | |
| 2367 | .slice => try airSlice(f, inst), | 2395 | .slice => try airSlice(f, inst), |
| 2368 | | 2396 | |
| 2369 | .cmp_gt => try airCmpOp(f, inst, ">"), | 2397 | .cmp_gt => try airCmpOp(f, inst, ">", "gt"), |
| 2370 | .cmp_gte => try airCmpOp(f, inst, ">="), | 2398 | .cmp_gte => try airCmpOp(f, inst, ">=", "ge"), |
| 2371 | .cmp_lt => try airCmpOp(f, inst, "<"), | 2399 | .cmp_lt => try airCmpOp(f, inst, "<", "lt"), |
| 2372 | .cmp_lte => try airCmpOp(f, inst, "<="), | 2400 | .cmp_lte => try airCmpOp(f, inst, "<=", "le"), |
| 2373 | | 2401 | |
| 2374 | .cmp_eq => try airEquality(f, inst, "((", "=="), | 2402 | .cmp_eq => try airEquality(f, inst, "((", "==", "eq"), |
| 2375 | .cmp_neq => try airEquality(f, inst, "!((", "!="), | 2403 | .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"), |
| 2376 | | 2404 | |
| 2377 | .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}), | 2405 | .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}), |
| 2378 | .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst), | 2406 | .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst), |
| ... | @@ -2468,7 +2496,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -2468,7 +2496,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2468 | .float_to_int, | 2496 | .float_to_int, |
| 2469 | .fptrunc, | 2497 | .fptrunc, |
| 2470 | .fpext, | 2498 | .fpext, |
| 2471 | => try airSimpleCast(f, inst), | 2499 | => try airFloatCast(f, inst), |
| 2472 | | 2500 | |
| 2473 | .ptrtoint => try airPtrToInt(f, inst), | 2501 | .ptrtoint => try airPtrToInt(f, inst), |
| 2474 | | 2502 | |
| ... | @@ -2973,8 +3001,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -2973,8 +3001,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2973 | | 3001 | |
| 2974 | const src_bits = src_ty.bitSize(target); | 3002 | const src_bits = src_ty.bitSize(target); |
| 2975 | | 3003 | |
| 2976 | const Limb = std.math.big.Limb; | 3004 | const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; |
| 2977 | const ExpectedContents = [BigInt.Managed.default_capacity]Limb; | | |
| 2978 | var stack align(@alignOf(ExpectedContents)) = | 3005 | var stack align(@alignOf(ExpectedContents)) = |
| 2979 | std.heap.stackFallback(@sizeOf(ExpectedContents), f.object.dg.gpa); | 3006 | std.heap.stackFallback(@sizeOf(ExpectedContents), f.object.dg.gpa); |
| 2980 | | 3007 | |
| ... | @@ -3081,7 +3108,7 @@ fn airBinOp( | ... | @@ -3081,7 +3108,7 @@ fn airBinOp( |
| 3081 | | 3108 | |
| 3082 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3109 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3083 | const target = f.object.dg.module.getTarget(); | 3110 | const target = f.object.dg.module.getTarget(); |
| 3084 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) | 3111 | if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat()) |
| 3085 | return try airBinBuiltinCall(f, inst, operation, info); | 3112 | return try airBinBuiltinCall(f, inst, operation, info); |
| 3086 | | 3113 | |
| 3087 | const inst_ty = f.air.typeOfIndex(inst); | 3114 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -3102,7 +3129,7 @@ fn airBinOp( | ... | @@ -3102,7 +3129,7 @@ fn airBinOp( |
| 3102 | return local; | 3129 | return local; |
| 3103 | } | 3130 | } |
| 3104 | | 3131 | |
| 3105 | fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { | 3132 | fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue { |
| 3106 | if (f.liveness.isUnused(inst)) return CValue.none; | 3133 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3107 | | 3134 | |
| 3108 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3135 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| ... | @@ -3110,7 +3137,9 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { | ... | @@ -3110,7 +3137,9 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { |
| 3110 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3137 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3111 | const target = f.object.dg.module.getTarget(); | 3138 | const target = f.object.dg.module.getTarget(); |
| 3112 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) | 3139 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) |
| 3113 | return try airCmpBuiltinCall(f, inst, operator); | 3140 | return try airCmpBuiltinCall(f, inst, operator, "cmp"); |
| | 3141 | if (operand_ty.isRuntimeFloat()) |
| | 3142 | return try airCmpBuiltinCall(f, inst, operator, operation); |
| 3114 | | 3143 | |
| 3115 | const inst_ty = f.air.typeOfIndex(inst); | 3144 | const inst_ty = f.air.typeOfIndex(inst); |
| 3116 | const lhs = try f.resolveInst(bin_op.lhs); | 3145 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -3134,11 +3163,20 @@ fn airEquality( | ... | @@ -3134,11 +3163,20 @@ fn airEquality( |
| 3134 | f: *Function, | 3163 | f: *Function, |
| 3135 | inst: Air.Inst.Index, | 3164 | inst: Air.Inst.Index, |
| 3136 | negate_prefix: []const u8, | 3165 | negate_prefix: []const u8, |
| 3137 | eq_op_str: []const u8, | 3166 | operator: []const u8, |
| | 3167 | operation: []const u8, |
| 3138 | ) !CValue { | 3168 | ) !CValue { |
| 3139 | if (f.liveness.isUnused(inst)) return CValue.none; | 3169 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3140 | | 3170 | |
| 3141 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3171 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| | 3172 | |
| | 3173 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| | 3174 | const target = f.object.dg.module.getTarget(); |
| | 3175 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) |
| | 3176 | return try airCmpBuiltinCall(f, inst, operator, "cmp"); |
| | 3177 | if (operand_ty.isRuntimeFloat()) |
| | 3178 | return try airCmpBuiltinCall(f, inst, operator, operation); |
| | 3179 | |
| 3142 | const lhs = try f.resolveInst(bin_op.lhs); | 3180 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3143 | const rhs = try f.resolveInst(bin_op.rhs); | 3181 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3144 | | 3182 | |
| ... | @@ -3148,8 +3186,7 @@ fn airEquality( | ... | @@ -3148,8 +3186,7 @@ fn airEquality( |
| 3148 | | 3186 | |
| 3149 | try writer.writeAll(" = "); | 3187 | try writer.writeAll(" = "); |
| 3150 | | 3188 | |
| 3151 | const lhs_ty = f.air.typeOf(bin_op.lhs); | 3189 | if (operand_ty.tag() == .optional) { |
| 3152 | if (lhs_ty.tag() == .optional) { | | |
| 3153 | // (A && B) || (C && (A == B)) | 3190 | // (A && B) || (C && (A == B)) |
| 3154 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload | 3191 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload |
| 3155 | | 3192 | |
| ... | @@ -3172,7 +3209,7 @@ fn airEquality( | ... | @@ -3172,7 +3209,7 @@ fn airEquality( |
| 3172 | | 3209 | |
| 3173 | try f.writeCValue(writer, lhs, .Other); | 3210 | try f.writeCValue(writer, lhs, .Other); |
| 3174 | try writer.writeByte(' '); | 3211 | try writer.writeByte(' '); |
| 3175 | try writer.writeAll(eq_op_str); | 3212 | try writer.writeAll(operator); |
| 3176 | try writer.writeByte(' '); | 3213 | try writer.writeByte(' '); |
| 3177 | try f.writeCValue(writer, rhs, .Other); | 3214 | try f.writeCValue(writer, rhs, .Other); |
| 3178 | try writer.writeAll(";\n"); | 3215 | try writer.writeAll(";\n"); |
| ... | @@ -3231,15 +3268,22 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -3231,15 +3268,22 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3231 | return local; | 3268 | return local; |
| 3232 | } | 3269 | } |
| 3233 | | 3270 | |
| 3234 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | 3271 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 3235 | if (f.liveness.isUnused(inst)) return CValue.none; | 3272 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3236 | | 3273 | |
| 3237 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3274 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| | 3275 | |
| | 3276 | const inst_ty = f.air.typeOfIndex(inst); |
| | 3277 | const target = f.object.dg.module.getTarget(); |
| | 3278 | if (inst_ty.isInt() and inst_ty.bitSize(target) > 64) |
| | 3279 | return try airBinBuiltinCall(f, inst, operation[1..], .None); |
| | 3280 | if (inst_ty.isRuntimeFloat()) |
| | 3281 | return try airBinFloatOp(f, inst, operation); |
| | 3282 | |
| 3238 | const lhs = try f.resolveInst(bin_op.lhs); | 3283 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3239 | const rhs = try f.resolveInst(bin_op.rhs); | 3284 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3240 | | 3285 | |
| 3241 | const writer = f.object.writer(); | 3286 | const writer = f.object.writer(); |
| 3242 | const inst_ty = f.air.typeOfIndex(inst); | | |
| 3243 | const local = try f.allocLocal(inst_ty, .Const); | 3287 | const local = try f.allocLocal(inst_ty, .Const); |
| 3244 | | 3288 | |
| 3245 | // (lhs <> rhs) ? lhs : rhs | 3289 | // (lhs <> rhs) ? lhs : rhs |
| ... | @@ -4518,19 +4562,44 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4518,19 +4562,44 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4518 | return local; | 4562 | return local; |
| 4519 | } | 4563 | } |
| 4520 | | 4564 | |
| 4521 | /// Emits a local variable with the result type and initializes it | 4565 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4522 | /// with the operand. | | |
| 4523 | fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue { | | |
| 4524 | if (f.liveness.isUnused(inst)) return CValue.none; | 4566 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 4525 | | 4567 | |
| 4526 | const inst_ty = f.air.typeOfIndex(inst); | 4568 | const inst_ty = f.air.typeOfIndex(inst); |
| 4527 | const local = try f.allocLocal(inst_ty, .Const); | | |
| 4528 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 4569 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 4529 | const writer = f.object.writer(); | | |
| 4530 | const operand = try f.resolveInst(ty_op.operand); | 4570 | const operand = try f.resolveInst(ty_op.operand); |
| | 4571 | const operand_ty = f.air.typeOf(ty_op.operand); |
| | 4572 | const target = f.object.dg.module.getTarget(); |
| | 4573 | const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) |
| | 4574 | if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend" |
| | 4575 | else if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) |
| | 4576 | if (inst_ty.isSignedInt()) "fix" else "fixuns" |
| | 4577 | else if (inst_ty.isRuntimeFloat() and operand_ty.isInt()) |
| | 4578 | if (operand_ty.isSignedInt()) "float" else "floatun" |
| | 4579 | else |
| | 4580 | unreachable; |
| | 4581 | |
| | 4582 | const local = try f.allocLocal(inst_ty, .Const); |
| | 4583 | const writer = f.object.writer(); |
| 4531 | | 4584 | |
| 4532 | try writer.writeAll(" = "); | 4585 | try writer.writeAll(" = "); |
| 4533 | try f.writeCValue(writer, operand, .Other); | 4586 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { |
| | 4587 | try writer.writeAll("zig_wrap_"); |
| | 4588 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| | 4589 | try writer.writeByte('('); |
| | 4590 | } |
| | 4591 | try writer.writeAll("__"); |
| | 4592 | try writer.writeAll(operation); |
| | 4593 | try writer.writeAll(compilerRtAbbrev(operand_ty, target)); |
| | 4594 | try writer.writeAll(compilerRtAbbrev(inst_ty, target)); |
| | 4595 | if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) try writer.writeByte('2'); |
| | 4596 | try writer.writeByte('('); |
| | 4597 | try f.writeCValue(writer, operand, .FunctionArgument); |
| | 4598 | try writer.writeByte(')'); |
| | 4599 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { |
| | 4600 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); |
| | 4601 | try writer.writeByte(')'); |
| | 4602 | } |
| 4534 | try writer.writeAll(";\n"); | 4603 | try writer.writeAll(";\n"); |
| 4535 | return local; | 4604 | return local; |
| 4536 | } | 4605 | } |
| ... | @@ -4604,7 +4673,12 @@ fn airBinBuiltinCall( | ... | @@ -4604,7 +4673,12 @@ fn airBinBuiltinCall( |
| 4604 | return local; | 4673 | return local; |
| 4605 | } | 4674 | } |
| 4606 | | 4675 | |
| 4607 | fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { | 4676 | fn airCmpBuiltinCall( |
| | 4677 | f: *Function, |
| | 4678 | inst: Air.Inst.Index, |
| | 4679 | operator: []const u8, |
| | 4680 | operation: []const u8, |
| | 4681 | ) !CValue { |
| 4608 | if (f.liveness.isUnused(inst)) return CValue.none; | 4682 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 4609 | | 4683 | |
| 4610 | const inst_ty = f.air.typeOfIndex(inst); | 4684 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -4613,7 +4687,9 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) ! | ... | @@ -4613,7 +4687,9 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) ! |
| 4613 | | 4687 | |
| 4614 | const local = try f.allocLocal(inst_ty, .Const); | 4688 | const local = try f.allocLocal(inst_ty, .Const); |
| 4615 | const writer = f.object.writer(); | 4689 | const writer = f.object.writer(); |
| 4616 | try writer.writeAll(" = zig_cmp_"); | 4690 | try writer.writeAll(" = zig_"); |
| | 4691 | try writer.writeAll(operation); |
| | 4692 | try writer.writeByte('_'); |
| 4617 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); | 4693 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 4618 | try writer.writeByte('('); | 4694 | try writer.writeByte('('); |
| 4619 | try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument); | 4695 | try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument); |
| ... | @@ -5157,17 +5233,21 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5157,17 +5233,21 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5157 | return local; | 5233 | return local; |
| 5158 | } | 5234 | } |
| 5159 | | 5235 | |
| 5160 | fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue { | 5236 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5161 | if (f.liveness.isUnused(inst)) return CValue.none; | 5237 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 5162 | | 5238 | |
| 5163 | const un_op = f.air.instructions.items(.data)[inst].un_op; | | |
| 5164 | const writer = f.object.writer(); | | |
| 5165 | const inst_ty = f.air.typeOfIndex(inst); | 5239 | const inst_ty = f.air.typeOfIndex(inst); |
| | 5240 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5166 | const operand = try f.resolveInst(un_op); | 5241 | const operand = try f.resolveInst(un_op); |
| | 5242 | const operand_ty = f.air.typeOf(un_op); |
| | 5243 | |
| 5167 | const local = try f.allocLocal(inst_ty, .Const); | 5244 | const local = try f.allocLocal(inst_ty, .Const); |
| 5168 | try writer.writeAll(" = -"); | 5245 | const writer = f.object.writer(); |
| 5169 | try f.writeCValue(writer, operand, .Other); | 5246 | try writer.writeAll(" = zig_neg_"); |
| 5170 | try writer.writeAll(";\n"); | 5247 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| | 5248 | try writer.writeByte('('); |
| | 5249 | try f.writeCValue(writer, operand, .FunctionArgument); |
| | 5250 | try writer.writeAll(");\n"); |
| 5171 | return local; | 5251 | return local; |
| 5172 | } | 5252 | } |
| 5173 | | 5253 | |
| ... | @@ -5178,7 +5258,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal | ... | @@ -5178,7 +5258,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 5178 | const inst_ty = f.air.typeOfIndex(inst); | 5258 | const inst_ty = f.air.typeOfIndex(inst); |
| 5179 | const operand = try f.resolveInst(un_op); | 5259 | const operand = try f.resolveInst(un_op); |
| 5180 | const local = try f.allocLocal(inst_ty, .Const); | 5260 | const local = try f.allocLocal(inst_ty, .Const); |
| 5181 | try writer.writeAll(" = zig_builtin_"); | 5261 | try writer.writeAll(" = zig_libc_name_"); |
| 5182 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5262 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5183 | try writer.writeByte('('); | 5263 | try writer.writeByte('('); |
| 5184 | try writer.writeAll(operation); | 5264 | try writer.writeAll(operation); |
| ... | @@ -5196,7 +5276,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -5196,7 +5276,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 5196 | const lhs = try f.resolveInst(bin_op.lhs); | 5276 | const lhs = try f.resolveInst(bin_op.lhs); |
| 5197 | const rhs = try f.resolveInst(bin_op.rhs); | 5277 | const rhs = try f.resolveInst(bin_op.rhs); |
| 5198 | const local = try f.allocLocal(inst_ty, .Const); | 5278 | const local = try f.allocLocal(inst_ty, .Const); |
| 5199 | try writer.writeAll(" = zig_builtin_"); | 5279 | try writer.writeAll(" = zig_libc_name_"); |
| 5200 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5280 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5201 | try writer.writeByte('('); | 5281 | try writer.writeByte('('); |
| 5202 | try writer.writeAll(operation); | 5282 | try writer.writeAll(operation); |
| ... | @@ -5218,7 +5298,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5218,7 +5298,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5218 | const addend = try f.resolveInst(pl_op.operand); | 5298 | const addend = try f.resolveInst(pl_op.operand); |
| 5219 | const writer = f.object.writer(); | 5299 | const writer = f.object.writer(); |
| 5220 | const local = try f.allocLocal(inst_ty, .Const); | 5300 | const local = try f.allocLocal(inst_ty, .Const); |
| 5221 | try writer.writeAll(" = zig_builtin_"); | 5301 | try writer.writeAll(" = zig_libc_name_"); |
| 5222 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5302 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5223 | try writer.writeAll("(fma)("); | 5303 | try writer.writeAll("(fma)("); |
| 5224 | try f.writeCValue(writer, mulend1, .FunctionArgument); | 5304 | try f.writeCValue(writer, mulend1, .FunctionArgument); |
| ... | @@ -5328,6 +5408,22 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { | ... | @@ -5328,6 +5408,22 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { |
| 5328 | }; | 5408 | }; |
| 5329 | } | 5409 | } |
| 5330 | | 5410 | |
| | 5411 | fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { |
| | 5412 | return if (ty.isInt()) switch (ty.intInfo(target).bits) { |
| | 5413 | 1...32 => "si", |
| | 5414 | 33...64 => "di", |
| | 5415 | 65...128 => "ti", |
| | 5416 | else => unreachable, |
| | 5417 | } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { |
| | 5418 | 16 => "hf", |
| | 5419 | 32 => "sf", |
| | 5420 | 64 => "df", |
| | 5421 | 80 => "xf", |
| | 5422 | 128 => "tf", |
| | 5423 | else => unreachable, |
| | 5424 | } else unreachable; |
| | 5425 | } |
| | 5426 | |
| 5331 | fn formatStringLiteral( | 5427 | fn formatStringLiteral( |
| 5332 | str: []const u8, | 5428 | str: []const u8, |
| 5333 | comptime fmt: []const u8, | 5429 | comptime fmt: []const u8, |
| ... | @@ -5356,8 +5452,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { | ... | @@ -5356,8 +5452,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { |
| 5356 | return .{ .data = str }; | 5452 | return .{ .data = str }; |
| 5357 | } | 5453 | } |
| 5358 | | 5454 | |
| 5359 | fn undefPattern(comptime T: type) T { | 5455 | fn undefPattern(comptime IntType: type) IntType { |
| 5360 | return (1 << (@bitSizeOf(T) | 1)) / 3; | 5456 | const int_info = @typeInfo(IntType).Int; |
| | 5457 | const UnsignedType = std.meta.Int(.unsigned, int_info.bits); |
| | 5458 | return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); |
| 5361 | } | 5459 | } |
| 5362 | | 5460 | |
| 5363 | const FormatIntLiteralContext = struct { | 5461 | const FormatIntLiteralContext = struct { |
| ... | @@ -5374,30 +5472,29 @@ fn formatIntLiteral( | ... | @@ -5374,30 +5472,29 @@ fn formatIntLiteral( |
| 5374 | const target = data.mod.getTarget(); | 5472 | const target = data.mod.getTarget(); |
| 5375 | const int_info = data.ty.intInfo(target); | 5473 | const int_info = data.ty.intInfo(target); |
| 5376 | | 5474 | |
| 5377 | const Limb = std.math.big.Limb; | | |
| 5378 | const ExpectedContents = struct { | 5475 | const ExpectedContents = struct { |
| 5379 | const base = 10; | 5476 | const base = 10; |
| 5380 | const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); | 5477 | const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); |
| 5381 | const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); | 5478 | const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); |
| 5382 | const worst_case_int = BigInt.Const{ | 5479 | const worst_case_int = BigInt.Const{ |
| 5383 | .limbs = &([1]Limb{std.math.maxInt(Limb)} ** expected_needed_limbs_count), | 5480 | .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count), |
| 5384 | .positive = false, | 5481 | .positive = false, |
| 5385 | }; | 5482 | }; |
| 5386 | | 5483 | |
| 5387 | undef_limbs: [limbs_count_128]Limb, | 5484 | undef_limbs: [limbs_count_128]BigIntLimb, |
| 5388 | wrap_limbs: [limbs_count_128]Limb, | 5485 | wrap_limbs: [limbs_count_128]BigIntLimb, |
| 5389 | }; | 5486 | }; |
| 5390 | var stack align(@alignOf(ExpectedContents)) = | 5487 | var stack align(@alignOf(ExpectedContents)) = |
| 5391 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa); | 5488 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa); |
| 5392 | const allocator = stack.get(); | 5489 | const allocator = stack.get(); |
| 5393 | | 5490 | |
| 5394 | var undef_limbs: []Limb = &.{}; | 5491 | var undef_limbs: []BigIntLimb = &.{}; |
| 5395 | defer allocator.free(undef_limbs); | 5492 | defer allocator.free(undef_limbs); |
| 5396 | | 5493 | |
| 5397 | var int_buf: Value.BigIntSpace = undefined; | 5494 | var int_buf: Value.BigIntSpace = undefined; |
| 5398 | const int = if (data.val.isUndefDeep()) blk: { | 5495 | const int = if (data.val.isUndefDeep()) blk: { |
| 5399 | undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits)); | 5496 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits)); |
| 5400 | std.mem.set(Limb, undef_limbs, undefPattern(Limb)); | 5497 | std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); |
| 5401 | | 5498 | |
| 5402 | var undef_int = BigInt.Mutable{ | 5499 | var undef_int = BigInt.Mutable{ |
| 5403 | .limbs = undef_limbs, | 5500 | .limbs = undef_limbs, |
| ... | @@ -5410,10 +5507,10 @@ fn formatIntLiteral( | ... | @@ -5410,10 +5507,10 @@ fn formatIntLiteral( |
| 5410 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); | 5507 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); |
| 5411 | | 5508 | |
| 5412 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; | 5509 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; |
| 5413 | var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined; | 5510 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 5414 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); | 5511 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 5415 | | 5512 | |
| 5416 | const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits)); | 5513 | const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)); |
| 5417 | defer allocator.free(wrap_limbs); | 5514 | defer allocator.free(wrap_limbs); |
| 5418 | var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; | 5515 | var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; |
| 5419 | if (wrap.addWrap(int, one, int_info.signedness, c_bits) or | 5516 | if (wrap.addWrap(int, one, int_info.signedness, c_bits) or |
| ... | @@ -5439,7 +5536,7 @@ fn formatIntLiteral( | ... | @@ -5439,7 +5536,7 @@ fn formatIntLiteral( |
| 5439 | else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), | 5536 | else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), |
| 5440 | } | 5537 | } |
| 5441 | | 5538 | |
| 5442 | const limbs_count_64 = @divExact(64, @bitSizeOf(Limb)); | 5539 | const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb)); |
| 5443 | if (c_bits <= 64) { | 5540 | if (c_bits <= 64) { |
| 5444 | var base: u8 = undefined; | 5541 | var base: u8 = undefined; |
| 5445 | var case: std.fmt.Case = undefined; | 5542 | var case: std.fmt.Case = undefined; |
| ... | @@ -5471,7 +5568,7 @@ fn formatIntLiteral( | ... | @@ -5471,7 +5568,7 @@ fn formatIntLiteral( |
| 5471 | } | 5568 | } |
| 5472 | | 5569 | |
| 5473 | var str: [64]u8 = undefined; | 5570 | var str: [64]u8 = undefined; |
| 5474 | var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined; | 5571 | var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined; |
| 5475 | try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]); | 5572 | try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]); |
| 5476 | } else { | 5573 | } else { |
| 5477 | assert(c_bits == 128); | 5574 | assert(c_bits == 128); |