Commit 4e85536604
Changed files (3)
src
codegen
llvm
test
behavior
src/codegen/llvm/Builder.zig
@@ -7339,28 +7339,36 @@ pub const Constant = enum(u32) {
.positive_integer,
.negative_integer,
=> |tag| {
- const extra: *align(@alignOf(std.math.big.Limb)) Integer =
+ const extra: *align(@alignOf(std.math.big.Limb)) const Integer =
@ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]);
const limbs = data.builder.constant_limbs
.items[item.data + Integer.limbs ..][0..extra.limbs_len];
const bigint: std.math.big.int.Const = .{
.limbs = limbs,
- .positive = tag == .positive_integer,
+ .positive = switch (tag) {
+ .positive_integer => true,
+ .negative_integer => false,
+ else => unreachable,
+ },
};
const ExpectedContents = extern struct {
- string: [(64 * 8 / std.math.log2(10)) + 2]u8,
+ const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
+ string: [
+ (std.math.big.int.Const{
+ .limbs = &([1]std.math.big.Limb{
+ std.math.maxInt(std.math.big.Limb),
+ } ** expected_limbs),
+ .positive = false,
+ }).sizeInBaseUpperBound(10)
+ ]u8,
limbs: [
- std.math.big.int.calcToStringLimbsBufferLen(
- 64 / @sizeOf(std.math.big.Limb),
- 10,
- )
+ std.math.big.int.calcToStringLimbsBufferLen(expected_limbs, 10)
]std.math.big.Limb,
};
var stack align(@alignOf(ExpectedContents)) =
std.heap.stackFallback(@sizeOf(ExpectedContents), data.builder.gpa);
const allocator = stack.get();
- const str = bigint.toStringAlloc(allocator, 10, undefined) catch
- return writer.writeAll("...");
+ const str = try bigint.toStringAlloc(allocator, 10, undefined);
defer allocator.free(str);
try writer.writeAll(str);
},
@@ -9464,10 +9472,38 @@ pub fn print(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocato
try bw.flush();
}
+fn WriterWithErrors(comptime BackingWriter: type, comptime ExtraErrors: type) type {
+ return struct {
+ backing_writer: BackingWriter,
+
+ pub const Error = BackingWriter.Error || ExtraErrors;
+ pub const Writer = std.io.Writer(*const Self, Error, write);
+
+ const Self = @This();
+
+ pub fn writer(self: *const Self) Writer {
+ return .{ .context = self };
+ }
+
+ pub fn write(self: *const Self, bytes: []const u8) Error!usize {
+ return self.backing_writer.write(bytes);
+ }
+ };
+}
+fn writerWithErrors(
+ backing_writer: anytype,
+ comptime ExtraErrors: type,
+) WriterWithErrors(@TypeOf(backing_writer), ExtraErrors) {
+ return .{ .backing_writer = backing_writer };
+}
+
pub fn printUnbuffered(
self: *Builder,
- writer: anytype,
-) (@TypeOf(writer).Error || Allocator.Error)!void {
+ backing_writer: anytype,
+) (@TypeOf(backing_writer).Error || Allocator.Error)!void {
+ const writer_with_errors = writerWithErrors(backing_writer, Allocator.Error);
+ const writer = writer_with_errors.writer();
+
var need_newline = false;
var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
defer metadata_formatter.map.deinit(self.gpa);
@@ -10344,12 +10380,17 @@ pub fn printUnbuffered(
const extra = self.metadataExtraData(Metadata.Enumerator, metadata_item.data);
const ExpectedContents = extern struct {
- string: [(64 * 8 / std.math.log2(10)) + 2]u8,
+ const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
+ string: [
+ (std.math.big.int.Const{
+ .limbs = &([1]std.math.big.Limb{
+ std.math.maxInt(std.math.big.Limb),
+ } ** expected_limbs),
+ .positive = false,
+ }).sizeInBaseUpperBound(10)
+ ]u8,
limbs: [
- std.math.big.int.calcToStringLimbsBufferLen(
- 64 / @sizeOf(std.math.big.Limb),
- 10,
- )
+ std.math.big.int.calcToStringLimbsBufferLen(expected_limbs, 10)
]std.math.big.Limb,
};
var stack align(@alignOf(ExpectedContents)) =
@@ -10375,7 +10416,9 @@ pub fn printUnbuffered(
.value = str,
.isUnsigned = switch (kind) {
.enumerator_unsigned => true,
- .enumerator_signed_positive, .enumerator_signed_negative => false,
+ .enumerator_signed_positive,
+ .enumerator_signed_negative,
+ => false,
else => unreachable,
},
}, writer);
@@ -13787,37 +13830,42 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
=> |tag| {
const extra: *align(@alignOf(std.math.big.Limb)) Constant.Integer =
@ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]);
- const limbs = self.constant_limbs
- .items[data + Constant.Integer.limbs ..][0..extra.limbs_len];
const bigint: std.math.big.int.Const = .{
- .limbs = limbs,
- .positive = tag == .positive_integer,
+ .limbs = self.constant_limbs
+ .items[data + Constant.Integer.limbs ..][0..extra.limbs_len],
+ .positive = switch (tag) {
+ .positive_integer => true,
+ .negative_integer => false,
+ else => unreachable,
+ },
};
-
const bit_count = extra.type.scalarBits(self);
- if (bit_count <= 64) {
- const val = bigint.to(i64) catch unreachable;
- const emit_val = if (tag == .positive_integer)
- @shlWithOverflow(val, 1)[0]
- else
- (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
- try constants_block.writeAbbrev(Constants.Integer{ .value = @bitCast(emit_val) });
- } else {
- const word_count = std.mem.alignForward(u24, bit_count, 64) / 64;
- try record.ensureUnusedCapacity(self.gpa, word_count);
- const buffer: [*]u8 = @ptrCast(record.items.ptr);
- bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
-
- const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
- for (signed_buffer[0..word_count], 0..) |val, i| {
- signed_buffer[i] = if (val >= 0)
- @shlWithOverflow(val, 1)[0]
+ const val: i64 = if (bit_count <= 64)
+ bigint.to(i64) catch unreachable
+ else if (bigint.to(u64)) |val|
+ @bitCast(val)
+ else |_| {
+ const limbs = try record.addManyAsSlice(
+ self.gpa,
+ std.math.divCeil(u24, bit_count, 64) catch unreachable,
+ );
+ bigint.writeTwosComplement(std.mem.sliceAsBytes(limbs), .little);
+ for (limbs) |*limb| {
+ const val = std.mem.littleToNative(i64, @bitCast(limb.*));
+ limb.* = @bitCast(if (val >= 0)
+ val << 1 | 0
else
- (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
+ -%val << 1 | 1);
}
-
- try constants_block.writeUnabbrev(5, record.items.ptr[0..word_count]);
- }
+ try constants_block.writeUnabbrev(5, record.items);
+ continue;
+ };
+ try constants_block.writeAbbrev(Constants.Integer{
+ .value = @bitCast(if (val >= 0)
+ val << 1 | 0
+ else
+ -%val << 1 | 1),
+ });
},
.half,
.bfloat,
@@ -14186,6 +14234,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
self.metadata_items.items(.tag)[1..],
self.metadata_items.items(.data)[1..],
) |tag, data| {
+ record.clearRetainingCapacity();
switch (tag) {
.none => unreachable,
.file => {
@@ -14333,77 +14382,60 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
.enumerator_signed_positive,
.enumerator_signed_negative,
=> |kind| {
- const positive = switch (kind) {
- .enumerator_unsigned,
- .enumerator_signed_positive,
- => true,
- .enumerator_signed_negative => false,
- else => unreachable,
- };
-
- const unsigned = switch (kind) {
- .enumerator_unsigned => true,
- .enumerator_signed_positive,
- .enumerator_signed_negative,
- => false,
- else => unreachable,
- };
-
const extra = self.metadataExtraData(Metadata.Enumerator, data);
-
- const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len];
-
const bigint: std.math.big.int.Const = .{
- .limbs = limbs,
- .positive = positive,
+ .limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len],
+ .positive = switch (kind) {
+ .enumerator_unsigned,
+ .enumerator_signed_positive,
+ => true,
+ .enumerator_signed_negative => false,
+ else => unreachable,
+ },
};
-
- if (extra.bit_width <= 64) {
- const val = bigint.to(i64) catch unreachable;
- const emit_val = if (positive)
- @shlWithOverflow(val, 1)[0]
- else
- (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
- try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{
- .flags = .{
- .unsigned = unsigned,
- },
- .bit_width = extra.bit_width,
- .name = extra.name,
- .value = @bitCast(emit_val),
- }, metadata_adapter);
- } else {
- const word_count = std.mem.alignForward(u32, extra.bit_width, 64) / 64;
- try record.ensureUnusedCapacity(self.gpa, 3 + word_count);
-
- const flags: MetadataBlock.Enumerator.Flags = .{
- .unsigned = unsigned,
- };
-
- const FlagsInt = @typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?;
-
- const flags_int: FlagsInt = @bitCast(flags);
-
- record.appendAssumeCapacity(@intCast(flags_int));
- record.appendAssumeCapacity(@intCast(extra.bit_width));
+ const flags: MetadataBlock.Enumerator.Flags = .{
+ .unsigned = switch (kind) {
+ .enumerator_unsigned => true,
+ .enumerator_signed_positive,
+ .enumerator_signed_negative,
+ => false,
+ else => unreachable,
+ },
+ };
+ const val: i64 = if (bigint.to(i64)) |val|
+ val
+ else |_| if (bigint.to(u64)) |val|
+ @bitCast(val)
+ else |_| {
+ const limbs_len = std.math.divCeil(u32, extra.bit_width, 64) catch unreachable;
+ try record.ensureTotalCapacity(self.gpa, 3 + limbs_len);
+ record.appendAssumeCapacity(@as(
+ @typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?,
+ @bitCast(flags),
+ ));
+ record.appendAssumeCapacity(extra.bit_width);
record.appendAssumeCapacity(metadata_adapter.getMetadataStringIndex(extra.name));
-
- const buffer: [*]u8 = @ptrCast(record.items.ptr);
- bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
-
- const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
- for (signed_buffer[0..word_count], 0..) |val, i| {
- signed_buffer[i] = if (val >= 0)
- @shlWithOverflow(val, 1)[0]
+ const limbs = record.addManyAsSliceAssumeCapacity(limbs_len);
+ bigint.writeTwosComplement(std.mem.sliceAsBytes(limbs), .little);
+ for (limbs) |*limb| {
+ const val = std.mem.littleToNative(i64, @bitCast(limb.*));
+ limb.* = @bitCast(if (val >= 0)
+ val << 1 | 0
else
- (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
+ -%val << 1 | 1);
}
-
- try metadata_block.writeUnabbrev(
- MetadataBlock.Enumerator.id,
- record.items.ptr[0..(3 + word_count)],
- );
- }
+ try metadata_block.writeUnabbrev(MetadataBlock.Enumerator.id, record.items);
+ continue;
+ };
+ try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{
+ .flags = flags,
+ .bit_width = extra.bit_width,
+ .name = extra.name,
+ .value = @bitCast(if (val >= 0)
+ val << 1 | 0
+ else
+ -%val << 1 | 1),
+ }, metadata_adapter);
},
.subrange => {
const extra = self.metadataExtraData(Metadata.Subrange, data);
@@ -14491,7 +14523,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
}, metadata_adapter);
},
}
- record.clearRetainingCapacity();
}
// Write named metadata
@@ -14615,7 +14646,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
}
pub fn getOffsetValueIndex(adapter: @This(), value: Value) u32 {
- return @subWithOverflow(adapter.offset(), adapter.getValueIndex(value))[0];
+ return adapter.offset() -% adapter.getValueIndex(value);
}
pub fn getOffsetValueSignedIndex(adapter: @This(), value: Value) i32 {
src/codegen/c.zig
@@ -4120,7 +4120,7 @@ fn airEquality(
const operand_ty = f.typeOf(bin_op.lhs);
const operand_bits = operand_ty.bitSize(zcu);
- if (operand_ty.isInt(zcu) and operand_bits > 64)
+ if (operand_ty.isAbiInt(zcu) and operand_bits > 64)
return airCmpBuiltinCall(
f,
inst,
@@ -4474,9 +4474,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func);
const writer = f.object.writer();
- try writer.writeAll("/* ");
+ try writer.writeAll("/* inline:");
try owner_decl.renderFullyQualifiedName(zcu, writer);
- try writer.writeAll(" */ ");
+ try writer.writeAll(" */\n");
return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
}
test/behavior/enum.zig
@@ -1263,3 +1263,44 @@ test "matching captures causes enum equivalence" {
comptime assert(@TypeOf(a) == @TypeOf(b));
try expect(@intFromEnum(a) == @intFromEnum(b));
}
+
+test "large enum field values" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+
+ {
+ const E = enum(u64) { min = std.math.minInt(u64), max = std.math.maxInt(u64) };
+ var e: E = .min;
+ try expect(e == .min);
+ try expect(@intFromEnum(e) == std.math.minInt(u64));
+ e = .max;
+ try expect(e == .max);
+ try expect(@intFromEnum(e) == std.math.maxInt(u64));
+ }
+ {
+ const E = enum(i64) { min = std.math.minInt(i64), max = std.math.maxInt(i64) };
+ var e: E = .min;
+ try expect(e == .min);
+ try expect(@intFromEnum(e) == std.math.minInt(i64));
+ e = .max;
+ try expect(e == .max);
+ try expect(@intFromEnum(e) == std.math.maxInt(i64));
+ }
+ {
+ const E = enum(u128) { min = std.math.minInt(u128), max = std.math.maxInt(u128) };
+ var e: E = .min;
+ try expect(e == .min);
+ try expect(@intFromEnum(e) == std.math.minInt(u128));
+ e = .max;
+ try expect(e == .max);
+ try expect(@intFromEnum(e) == std.math.maxInt(u128));
+ }
+ {
+ const E = enum(i128) { min = std.math.minInt(i128), max = std.math.maxInt(i128) };
+ var e: E = .min;
+ try expect(e == .min);
+ try expect(@intFromEnum(e) == std.math.minInt(i128));
+ e = .max;
+ try expect(e == .max);
+ try expect(@intFromEnum(e) == std.math.maxInt(i128));
+ }
+}