| ... | @@ -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 | |
| ... | @@ -3003,6 +3030,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3003,6 +3030,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3003 | try writer.writeAll("(("); | 3030 | try writer.writeAll("(("); |
| 3004 | try f.renderTypecast(writer, host_ty); | 3031 | try f.renderTypecast(writer, host_ty); |
| 3005 | try writer.writeByte(')'); | 3032 | try writer.writeByte(')'); |
| | 3033 | if (src_ty.isPtrAtRuntime()) { |
| | 3034 | try writer.writeByte('('); |
| | 3035 | try f.renderTypecast(writer, Type.usize); |
| | 3036 | try writer.writeByte(')'); |
| | 3037 | } |
| 3006 | try f.writeCValue(writer, src_val, .Other); | 3038 | try f.writeCValue(writer, src_val, .Other); |
| 3007 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); | 3039 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); |
| 3008 | } else { | 3040 | } else { |
| ... | @@ -3081,7 +3113,7 @@ fn airBinOp( | ... | @@ -3081,7 +3113,7 @@ fn airBinOp( |
| 3081 | | 3113 | |
| 3082 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3114 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3083 | const target = f.object.dg.module.getTarget(); | 3115 | const target = f.object.dg.module.getTarget(); |
| 3084 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) | 3116 | if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat()) |
| 3085 | return try airBinBuiltinCall(f, inst, operation, info); | 3117 | return try airBinBuiltinCall(f, inst, operation, info); |
| 3086 | | 3118 | |
| 3087 | const inst_ty = f.air.typeOfIndex(inst); | 3119 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -3102,7 +3134,7 @@ fn airBinOp( | ... | @@ -3102,7 +3134,7 @@ fn airBinOp( |
| 3102 | return local; | 3134 | return local; |
| 3103 | } | 3135 | } |
| 3104 | | 3136 | |
| 3105 | fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { | 3137 | fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue { |
| 3106 | if (f.liveness.isUnused(inst)) return CValue.none; | 3138 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3107 | | 3139 | |
| 3108 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3140 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| ... | @@ -3110,7 +3142,9 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { | ... | @@ -3110,7 +3142,9 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { |
| 3110 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3142 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3111 | const target = f.object.dg.module.getTarget(); | 3143 | const target = f.object.dg.module.getTarget(); |
| 3112 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) | 3144 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) |
| 3113 | return try airCmpBuiltinCall(f, inst, operator); | 3145 | return try airCmpBuiltinCall(f, inst, operator, "cmp"); |
| | 3146 | if (operand_ty.isRuntimeFloat()) |
| | 3147 | return try airCmpBuiltinCall(f, inst, operator, operation); |
| 3114 | | 3148 | |
| 3115 | const inst_ty = f.air.typeOfIndex(inst); | 3149 | const inst_ty = f.air.typeOfIndex(inst); |
| 3116 | const lhs = try f.resolveInst(bin_op.lhs); | 3150 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -3134,11 +3168,20 @@ fn airEquality( | ... | @@ -3134,11 +3168,20 @@ fn airEquality( |
| 3134 | f: *Function, | 3168 | f: *Function, |
| 3135 | inst: Air.Inst.Index, | 3169 | inst: Air.Inst.Index, |
| 3136 | negate_prefix: []const u8, | 3170 | negate_prefix: []const u8, |
| 3137 | eq_op_str: []const u8, | 3171 | operator: []const u8, |
| | 3172 | operation: []const u8, |
| 3138 | ) !CValue { | 3173 | ) !CValue { |
| 3139 | if (f.liveness.isUnused(inst)) return CValue.none; | 3174 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3140 | | 3175 | |
| 3141 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3176 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| | 3177 | |
| | 3178 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| | 3179 | const target = f.object.dg.module.getTarget(); |
| | 3180 | if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) |
| | 3181 | return try airCmpBuiltinCall(f, inst, operator, "cmp"); |
| | 3182 | if (operand_ty.isRuntimeFloat()) |
| | 3183 | return try airCmpBuiltinCall(f, inst, operator, operation); |
| | 3184 | |
| 3142 | const lhs = try f.resolveInst(bin_op.lhs); | 3185 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3143 | const rhs = try f.resolveInst(bin_op.rhs); | 3186 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3144 | | 3187 | |
| ... | @@ -3148,8 +3191,7 @@ fn airEquality( | ... | @@ -3148,8 +3191,7 @@ fn airEquality( |
| 3148 | | 3191 | |
| 3149 | try writer.writeAll(" = "); | 3192 | try writer.writeAll(" = "); |
| 3150 | | 3193 | |
| 3151 | const lhs_ty = f.air.typeOf(bin_op.lhs); | 3194 | if (operand_ty.tag() == .optional) { |
| 3152 | if (lhs_ty.tag() == .optional) { | | |
| 3153 | // (A && B) || (C && (A == B)) | 3195 | // (A && B) || (C && (A == B)) |
| 3154 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload | 3196 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload |
| 3155 | | 3197 | |
| ... | @@ -3172,7 +3214,7 @@ fn airEquality( | ... | @@ -3172,7 +3214,7 @@ fn airEquality( |
| 3172 | | 3214 | |
| 3173 | try f.writeCValue(writer, lhs, .Other); | 3215 | try f.writeCValue(writer, lhs, .Other); |
| 3174 | try writer.writeByte(' '); | 3216 | try writer.writeByte(' '); |
| 3175 | try writer.writeAll(eq_op_str); | 3217 | try writer.writeAll(operator); |
| 3176 | try writer.writeByte(' '); | 3218 | try writer.writeByte(' '); |
| 3177 | try f.writeCValue(writer, rhs, .Other); | 3219 | try f.writeCValue(writer, rhs, .Other); |
| 3178 | try writer.writeAll(";\n"); | 3220 | try writer.writeAll(";\n"); |
| ... | @@ -3231,15 +3273,22 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -3231,15 +3273,22 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3231 | return local; | 3273 | return local; |
| 3232 | } | 3274 | } |
| 3233 | | 3275 | |
| 3234 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | 3276 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 3235 | if (f.liveness.isUnused(inst)) return CValue.none; | 3277 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3236 | | 3278 | |
| 3237 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3279 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| | 3280 | |
| | 3281 | const inst_ty = f.air.typeOfIndex(inst); |
| | 3282 | const target = f.object.dg.module.getTarget(); |
| | 3283 | if (inst_ty.isInt() and inst_ty.bitSize(target) > 64) |
| | 3284 | return try airBinBuiltinCall(f, inst, operation[1..], .None); |
| | 3285 | if (inst_ty.isRuntimeFloat()) |
| | 3286 | return try airBinFloatOp(f, inst, operation); |
| | 3287 | |
| 3238 | const lhs = try f.resolveInst(bin_op.lhs); | 3288 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3239 | const rhs = try f.resolveInst(bin_op.rhs); | 3289 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3240 | | 3290 | |
| 3241 | const writer = f.object.writer(); | 3291 | const writer = f.object.writer(); |
| 3242 | const inst_ty = f.air.typeOfIndex(inst); | | |
| 3243 | const local = try f.allocLocal(inst_ty, .Const); | 3292 | const local = try f.allocLocal(inst_ty, .Const); |
| 3244 | | 3293 | |
| 3245 | // (lhs <> rhs) ? lhs : rhs | 3294 | // (lhs <> rhs) ? lhs : rhs |
| ... | @@ -4518,19 +4567,44 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4518,19 +4567,44 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4518 | return local; | 4567 | return local; |
| 4519 | } | 4568 | } |
| 4520 | | 4569 | |
| 4521 | /// Emits a local variable with the result type and initializes it | 4570 | 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; | 4571 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 4525 | | 4572 | |
| 4526 | const inst_ty = f.air.typeOfIndex(inst); | 4573 | 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; | 4574 | 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); | 4575 | const operand = try f.resolveInst(ty_op.operand); |
| | 4576 | const operand_ty = f.air.typeOf(ty_op.operand); |
| | 4577 | const target = f.object.dg.module.getTarget(); |
| | 4578 | const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) |
| | 4579 | if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend" |
| | 4580 | else if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) |
| | 4581 | if (inst_ty.isSignedInt()) "fix" else "fixuns" |
| | 4582 | else if (inst_ty.isRuntimeFloat() and operand_ty.isInt()) |
| | 4583 | if (operand_ty.isSignedInt()) "float" else "floatun" |
| | 4584 | else |
| | 4585 | unreachable; |
| | 4586 | |
| | 4587 | const local = try f.allocLocal(inst_ty, .Const); |
| | 4588 | const writer = f.object.writer(); |
| 4531 | | 4589 | |
| 4532 | try writer.writeAll(" = "); | 4590 | try writer.writeAll(" = "); |
| 4533 | try f.writeCValue(writer, operand, .Other); | 4591 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { |
| | 4592 | try writer.writeAll("zig_wrap_"); |
| | 4593 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| | 4594 | try writer.writeByte('('); |
| | 4595 | } |
| | 4596 | try writer.writeAll("__"); |
| | 4597 | try writer.writeAll(operation); |
| | 4598 | try writer.writeAll(compilerRtAbbrev(operand_ty, target)); |
| | 4599 | try writer.writeAll(compilerRtAbbrev(inst_ty, target)); |
| | 4600 | if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) try writer.writeByte('2'); |
| | 4601 | try writer.writeByte('('); |
| | 4602 | try f.writeCValue(writer, operand, .FunctionArgument); |
| | 4603 | try writer.writeByte(')'); |
| | 4604 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { |
| | 4605 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); |
| | 4606 | try writer.writeByte(')'); |
| | 4607 | } |
| 4534 | try writer.writeAll(";\n"); | 4608 | try writer.writeAll(";\n"); |
| 4535 | return local; | 4609 | return local; |
| 4536 | } | 4610 | } |
| ... | @@ -4604,7 +4678,12 @@ fn airBinBuiltinCall( | ... | @@ -4604,7 +4678,12 @@ fn airBinBuiltinCall( |
| 4604 | return local; | 4678 | return local; |
| 4605 | } | 4679 | } |
| 4606 | | 4680 | |
| 4607 | fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { | 4681 | fn airCmpBuiltinCall( |
| | 4682 | f: *Function, |
| | 4683 | inst: Air.Inst.Index, |
| | 4684 | operator: []const u8, |
| | 4685 | operation: []const u8, |
| | 4686 | ) !CValue { |
| 4608 | if (f.liveness.isUnused(inst)) return CValue.none; | 4687 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 4609 | | 4688 | |
| 4610 | const inst_ty = f.air.typeOfIndex(inst); | 4689 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -4613,7 +4692,9 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) ! | ... | @@ -4613,7 +4692,9 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) ! |
| 4613 | | 4692 | |
| 4614 | const local = try f.allocLocal(inst_ty, .Const); | 4693 | const local = try f.allocLocal(inst_ty, .Const); |
| 4615 | const writer = f.object.writer(); | 4694 | const writer = f.object.writer(); |
| 4616 | try writer.writeAll(" = zig_cmp_"); | 4695 | try writer.writeAll(" = zig_"); |
| | 4696 | try writer.writeAll(operation); |
| | 4697 | try writer.writeByte('_'); |
| 4617 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); | 4698 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 4618 | try writer.writeByte('('); | 4699 | try writer.writeByte('('); |
| 4619 | try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument); | 4700 | try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument); |
| ... | @@ -5045,6 +5126,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5045,6 +5126,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5045 | try writer.writeAll("(("); | 5126 | try writer.writeAll("(("); |
| 5046 | try f.renderTypecast(writer, inst_ty); | 5127 | try f.renderTypecast(writer, inst_ty); |
| 5047 | try writer.writeByte(')'); | 5128 | try writer.writeByte(')'); |
| | 5129 | if (field_ty.isPtrAtRuntime()) { |
| | 5130 | try writer.writeByte('('); |
| | 5131 | try f.renderTypecast(writer, switch (int_info.signedness) { |
| | 5132 | .unsigned => Type.usize, |
| | 5133 | .signed => Type.isize, |
| | 5134 | }); |
| | 5135 | try writer.writeByte(')'); |
| | 5136 | } |
| 5048 | try f.writeCValue(writer, try f.resolveInst(element), .Other); | 5137 | try f.writeCValue(writer, try f.resolveInst(element), .Other); |
| 5049 | try writer.writeAll(", "); | 5138 | try writer.writeAll(", "); |
| 5050 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | 5139 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); |
| ... | @@ -5157,17 +5246,21 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5157,17 +5246,21 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5157 | return local; | 5246 | return local; |
| 5158 | } | 5247 | } |
| 5159 | | 5248 | |
| 5160 | fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue { | 5249 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5161 | if (f.liveness.isUnused(inst)) return CValue.none; | 5250 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 5162 | | 5251 | |
| 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); | 5252 | const inst_ty = f.air.typeOfIndex(inst); |
| | 5253 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5166 | const operand = try f.resolveInst(un_op); | 5254 | const operand = try f.resolveInst(un_op); |
| | 5255 | const operand_ty = f.air.typeOf(un_op); |
| | 5256 | |
| 5167 | const local = try f.allocLocal(inst_ty, .Const); | 5257 | const local = try f.allocLocal(inst_ty, .Const); |
| 5168 | try writer.writeAll(" = -"); | 5258 | const writer = f.object.writer(); |
| 5169 | try f.writeCValue(writer, operand, .Other); | 5259 | try writer.writeAll(" = zig_neg_"); |
| 5170 | try writer.writeAll(";\n"); | 5260 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| | 5261 | try writer.writeByte('('); |
| | 5262 | try f.writeCValue(writer, operand, .FunctionArgument); |
| | 5263 | try writer.writeAll(");\n"); |
| 5171 | return local; | 5264 | return local; |
| 5172 | } | 5265 | } |
| 5173 | | 5266 | |
| ... | @@ -5178,7 +5271,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal | ... | @@ -5178,7 +5271,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 5178 | const inst_ty = f.air.typeOfIndex(inst); | 5271 | const inst_ty = f.air.typeOfIndex(inst); |
| 5179 | const operand = try f.resolveInst(un_op); | 5272 | const operand = try f.resolveInst(un_op); |
| 5180 | const local = try f.allocLocal(inst_ty, .Const); | 5273 | const local = try f.allocLocal(inst_ty, .Const); |
| 5181 | try writer.writeAll(" = zig_builtin_"); | 5274 | try writer.writeAll(" = zig_libc_name_"); |
| 5182 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5275 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5183 | try writer.writeByte('('); | 5276 | try writer.writeByte('('); |
| 5184 | try writer.writeAll(operation); | 5277 | try writer.writeAll(operation); |
| ... | @@ -5196,7 +5289,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -5196,7 +5289,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 5196 | const lhs = try f.resolveInst(bin_op.lhs); | 5289 | const lhs = try f.resolveInst(bin_op.lhs); |
| 5197 | const rhs = try f.resolveInst(bin_op.rhs); | 5290 | const rhs = try f.resolveInst(bin_op.rhs); |
| 5198 | const local = try f.allocLocal(inst_ty, .Const); | 5291 | const local = try f.allocLocal(inst_ty, .Const); |
| 5199 | try writer.writeAll(" = zig_builtin_"); | 5292 | try writer.writeAll(" = zig_libc_name_"); |
| 5200 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5293 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5201 | try writer.writeByte('('); | 5294 | try writer.writeByte('('); |
| 5202 | try writer.writeAll(operation); | 5295 | try writer.writeAll(operation); |
| ... | @@ -5218,7 +5311,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5218,7 +5311,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5218 | const addend = try f.resolveInst(pl_op.operand); | 5311 | const addend = try f.resolveInst(pl_op.operand); |
| 5219 | const writer = f.object.writer(); | 5312 | const writer = f.object.writer(); |
| 5220 | const local = try f.allocLocal(inst_ty, .Const); | 5313 | const local = try f.allocLocal(inst_ty, .Const); |
| 5221 | try writer.writeAll(" = zig_builtin_"); | 5314 | try writer.writeAll(" = zig_libc_name_"); |
| 5222 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5315 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5223 | try writer.writeAll("(fma)("); | 5316 | try writer.writeAll("(fma)("); |
| 5224 | try f.writeCValue(writer, mulend1, .FunctionArgument); | 5317 | try f.writeCValue(writer, mulend1, .FunctionArgument); |
| ... | @@ -5328,6 +5421,22 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { | ... | @@ -5328,6 +5421,22 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { |
| 5328 | }; | 5421 | }; |
| 5329 | } | 5422 | } |
| 5330 | | 5423 | |
| | 5424 | fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { |
| | 5425 | return if (ty.isInt()) switch (ty.intInfo(target).bits) { |
| | 5426 | 1...32 => "si", |
| | 5427 | 33...64 => "di", |
| | 5428 | 65...128 => "ti", |
| | 5429 | else => unreachable, |
| | 5430 | } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { |
| | 5431 | 16 => "hf", |
| | 5432 | 32 => "sf", |
| | 5433 | 64 => "df", |
| | 5434 | 80 => "xf", |
| | 5435 | 128 => "tf", |
| | 5436 | else => unreachable, |
| | 5437 | } else unreachable; |
| | 5438 | } |
| | 5439 | |
| 5331 | fn formatStringLiteral( | 5440 | fn formatStringLiteral( |
| 5332 | str: []const u8, | 5441 | str: []const u8, |
| 5333 | comptime fmt: []const u8, | 5442 | comptime fmt: []const u8, |
| ... | @@ -5356,8 +5465,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { | ... | @@ -5356,8 +5465,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { |
| 5356 | return .{ .data = str }; | 5465 | return .{ .data = str }; |
| 5357 | } | 5466 | } |
| 5358 | | 5467 | |
| 5359 | fn undefPattern(comptime T: type) T { | 5468 | fn undefPattern(comptime IntType: type) IntType { |
| 5360 | return (1 << (@bitSizeOf(T) | 1)) / 3; | 5469 | const int_info = @typeInfo(IntType).Int; |
| | 5470 | const UnsignedType = std.meta.Int(.unsigned, int_info.bits); |
| | 5471 | return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); |
| 5361 | } | 5472 | } |
| 5362 | | 5473 | |
| 5363 | const FormatIntLiteralContext = struct { | 5474 | const FormatIntLiteralContext = struct { |
| ... | @@ -5374,30 +5485,29 @@ fn formatIntLiteral( | ... | @@ -5374,30 +5485,29 @@ fn formatIntLiteral( |
| 5374 | const target = data.mod.getTarget(); | 5485 | const target = data.mod.getTarget(); |
| 5375 | const int_info = data.ty.intInfo(target); | 5486 | const int_info = data.ty.intInfo(target); |
| 5376 | | 5487 | |
| 5377 | const Limb = std.math.big.Limb; | | |
| 5378 | const ExpectedContents = struct { | 5488 | const ExpectedContents = struct { |
| 5379 | const base = 10; | 5489 | const base = 10; |
| 5380 | const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); | 5490 | const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); |
| 5381 | const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); | 5491 | const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); |
| 5382 | const worst_case_int = BigInt.Const{ | 5492 | const worst_case_int = BigInt.Const{ |
| 5383 | .limbs = &([1]Limb{std.math.maxInt(Limb)} ** expected_needed_limbs_count), | 5493 | .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count), |
| 5384 | .positive = false, | 5494 | .positive = false, |
| 5385 | }; | 5495 | }; |
| 5386 | | 5496 | |
| 5387 | undef_limbs: [limbs_count_128]Limb, | 5497 | undef_limbs: [limbs_count_128]BigIntLimb, |
| 5388 | wrap_limbs: [limbs_count_128]Limb, | 5498 | wrap_limbs: [limbs_count_128]BigIntLimb, |
| 5389 | }; | 5499 | }; |
| 5390 | var stack align(@alignOf(ExpectedContents)) = | 5500 | var stack align(@alignOf(ExpectedContents)) = |
| 5391 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa); | 5501 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa); |
| 5392 | const allocator = stack.get(); | 5502 | const allocator = stack.get(); |
| 5393 | | 5503 | |
| 5394 | var undef_limbs: []Limb = &.{}; | 5504 | var undef_limbs: []BigIntLimb = &.{}; |
| 5395 | defer allocator.free(undef_limbs); | 5505 | defer allocator.free(undef_limbs); |
| 5396 | | 5506 | |
| 5397 | var int_buf: Value.BigIntSpace = undefined; | 5507 | var int_buf: Value.BigIntSpace = undefined; |
| 5398 | const int = if (data.val.isUndefDeep()) blk: { | 5508 | const int = if (data.val.isUndefDeep()) blk: { |
| 5399 | undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits)); | 5509 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits)); |
| 5400 | std.mem.set(Limb, undef_limbs, undefPattern(Limb)); | 5510 | std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); |
| 5401 | | 5511 | |
| 5402 | var undef_int = BigInt.Mutable{ | 5512 | var undef_int = BigInt.Mutable{ |
| 5403 | .limbs = undef_limbs, | 5513 | .limbs = undef_limbs, |
| ... | @@ -5410,10 +5520,10 @@ fn formatIntLiteral( | ... | @@ -5410,10 +5520,10 @@ fn formatIntLiteral( |
| 5410 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); | 5520 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); |
| 5411 | | 5521 | |
| 5412 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; | 5522 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; |
| 5413 | var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined; | 5523 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 5414 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); | 5524 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 5415 | | 5525 | |
| 5416 | const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits)); | 5526 | const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)); |
| 5417 | defer allocator.free(wrap_limbs); | 5527 | defer allocator.free(wrap_limbs); |
| 5418 | var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; | 5528 | var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; |
| 5419 | if (wrap.addWrap(int, one, int_info.signedness, c_bits) or | 5529 | if (wrap.addWrap(int, one, int_info.signedness, c_bits) or |
| ... | @@ -5439,7 +5549,7 @@ fn formatIntLiteral( | ... | @@ -5439,7 +5549,7 @@ fn formatIntLiteral( |
| 5439 | else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), | 5549 | else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), |
| 5440 | } | 5550 | } |
| 5441 | | 5551 | |
| 5442 | const limbs_count_64 = @divExact(64, @bitSizeOf(Limb)); | 5552 | const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb)); |
| 5443 | if (c_bits <= 64) { | 5553 | if (c_bits <= 64) { |
| 5444 | var base: u8 = undefined; | 5554 | var base: u8 = undefined; |
| 5445 | var case: std.fmt.Case = undefined; | 5555 | var case: std.fmt.Case = undefined; |
| ... | @@ -5471,7 +5581,7 @@ fn formatIntLiteral( | ... | @@ -5471,7 +5581,7 @@ fn formatIntLiteral( |
| 5471 | } | 5581 | } |
| 5472 | | 5582 | |
| 5473 | var str: [64]u8 = undefined; | 5583 | var str: [64]u8 = undefined; |
| 5474 | var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined; | 5584 | 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)]); | 5585 | try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]); |
| 5476 | } else { | 5586 | } else { |
| 5477 | assert(c_bits == 128); | 5587 | assert(c_bits == 128); |