Skip to content

Commit 4e85536

Browse files
jacobly0andrewrk
authored andcommitted
Builder: fix encoding big integers in bitcode
Closes #19543
1 parent 9ab6d91 commit 4e85536

File tree

3 files changed

+185
-113
lines changed

3 files changed

+185
-113
lines changed

src/codegen/c.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4120,7 +4120,7 @@ fn airEquality(
41204120

41214121
const operand_ty = f.typeOf(bin_op.lhs);
41224122
const operand_bits = operand_ty.bitSize(zcu);
4123-
if (operand_ty.isInt(zcu) and operand_bits > 64)
4123+
if (operand_ty.isAbiInt(zcu) and operand_bits > 64)
41244124
return airCmpBuiltinCall(
41254125
f,
41264126
inst,
@@ -4474,9 +4474,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
44744474
const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
44754475
const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func);
44764476
const writer = f.object.writer();
4477-
try writer.writeAll("/* ");
4477+
try writer.writeAll("/* inline:");
44784478
try owner_decl.renderFullyQualifiedName(zcu, writer);
4479-
try writer.writeAll(" */ ");
4479+
try writer.writeAll(" */\n");
44804480
return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
44814481
}
44824482

src/codegen/llvm/Builder.zig

Lines changed: 141 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7339,28 +7339,36 @@ pub const Constant = enum(u32) {
73397339
.positive_integer,
73407340
.negative_integer,
73417341
=> |tag| {
7342-
const extra: *align(@alignOf(std.math.big.Limb)) Integer =
7342+
const extra: *align(@alignOf(std.math.big.Limb)) const Integer =
73437343
@ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]);
73447344
const limbs = data.builder.constant_limbs
73457345
.items[item.data + Integer.limbs ..][0..extra.limbs_len];
73467346
const bigint: std.math.big.int.Const = .{
73477347
.limbs = limbs,
7348-
.positive = tag == .positive_integer,
7348+
.positive = switch (tag) {
7349+
.positive_integer => true,
7350+
.negative_integer => false,
7351+
else => unreachable,
7352+
},
73497353
};
73507354
const ExpectedContents = extern struct {
7351-
string: [(64 * 8 / std.math.log2(10)) + 2]u8,
7355+
const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
7356+
string: [
7357+
(std.math.big.int.Const{
7358+
.limbs = &([1]std.math.big.Limb{
7359+
std.math.maxInt(std.math.big.Limb),
7360+
} ** expected_limbs),
7361+
.positive = false,
7362+
}).sizeInBaseUpperBound(10)
7363+
]u8,
73527364
limbs: [
7353-
std.math.big.int.calcToStringLimbsBufferLen(
7354-
64 / @sizeOf(std.math.big.Limb),
7355-
10,
7356-
)
7365+
std.math.big.int.calcToStringLimbsBufferLen(expected_limbs, 10)
73577366
]std.math.big.Limb,
73587367
};
73597368
var stack align(@alignOf(ExpectedContents)) =
73607369
std.heap.stackFallback(@sizeOf(ExpectedContents), data.builder.gpa);
73617370
const allocator = stack.get();
7362-
const str = bigint.toStringAlloc(allocator, 10, undefined) catch
7363-
return writer.writeAll("...");
7371+
const str = try bigint.toStringAlloc(allocator, 10, undefined);
73647372
defer allocator.free(str);
73657373
try writer.writeAll(str);
73667374
},
@@ -9464,10 +9472,38 @@ pub fn print(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocato
94649472
try bw.flush();
94659473
}
94669474

9475+
fn WriterWithErrors(comptime BackingWriter: type, comptime ExtraErrors: type) type {
9476+
return struct {
9477+
backing_writer: BackingWriter,
9478+
9479+
pub const Error = BackingWriter.Error || ExtraErrors;
9480+
pub const Writer = std.io.Writer(*const Self, Error, write);
9481+
9482+
const Self = @This();
9483+
9484+
pub fn writer(self: *const Self) Writer {
9485+
return .{ .context = self };
9486+
}
9487+
9488+
pub fn write(self: *const Self, bytes: []const u8) Error!usize {
9489+
return self.backing_writer.write(bytes);
9490+
}
9491+
};
9492+
}
9493+
fn writerWithErrors(
9494+
backing_writer: anytype,
9495+
comptime ExtraErrors: type,
9496+
) WriterWithErrors(@TypeOf(backing_writer), ExtraErrors) {
9497+
return .{ .backing_writer = backing_writer };
9498+
}
9499+
94679500
pub fn printUnbuffered(
94689501
self: *Builder,
9469-
writer: anytype,
9470-
) (@TypeOf(writer).Error || Allocator.Error)!void {
9502+
backing_writer: anytype,
9503+
) (@TypeOf(backing_writer).Error || Allocator.Error)!void {
9504+
const writer_with_errors = writerWithErrors(backing_writer, Allocator.Error);
9505+
const writer = writer_with_errors.writer();
9506+
94719507
var need_newline = false;
94729508
var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
94739509
defer metadata_formatter.map.deinit(self.gpa);
@@ -10344,12 +10380,17 @@ pub fn printUnbuffered(
1034410380
const extra = self.metadataExtraData(Metadata.Enumerator, metadata_item.data);
1034510381

1034610382
const ExpectedContents = extern struct {
10347-
string: [(64 * 8 / std.math.log2(10)) + 2]u8,
10383+
const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
10384+
string: [
10385+
(std.math.big.int.Const{
10386+
.limbs = &([1]std.math.big.Limb{
10387+
std.math.maxInt(std.math.big.Limb),
10388+
} ** expected_limbs),
10389+
.positive = false,
10390+
}).sizeInBaseUpperBound(10)
10391+
]u8,
1034810392
limbs: [
10349-
std.math.big.int.calcToStringLimbsBufferLen(
10350-
64 / @sizeOf(std.math.big.Limb),
10351-
10,
10352-
)
10393+
std.math.big.int.calcToStringLimbsBufferLen(expected_limbs, 10)
1035310394
]std.math.big.Limb,
1035410395
};
1035510396
var stack align(@alignOf(ExpectedContents)) =
@@ -10375,7 +10416,9 @@ pub fn printUnbuffered(
1037510416
.value = str,
1037610417
.isUnsigned = switch (kind) {
1037710418
.enumerator_unsigned => true,
10378-
.enumerator_signed_positive, .enumerator_signed_negative => false,
10419+
.enumerator_signed_positive,
10420+
.enumerator_signed_negative,
10421+
=> false,
1037910422
else => unreachable,
1038010423
},
1038110424
}, writer);
@@ -13787,37 +13830,42 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1378713830
=> |tag| {
1378813831
const extra: *align(@alignOf(std.math.big.Limb)) Constant.Integer =
1378913832
@ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]);
13790-
const limbs = self.constant_limbs
13791-
.items[data + Constant.Integer.limbs ..][0..extra.limbs_len];
1379213833
const bigint: std.math.big.int.Const = .{
13793-
.limbs = limbs,
13794-
.positive = tag == .positive_integer,
13834+
.limbs = self.constant_limbs
13835+
.items[data + Constant.Integer.limbs ..][0..extra.limbs_len],
13836+
.positive = switch (tag) {
13837+
.positive_integer => true,
13838+
.negative_integer => false,
13839+
else => unreachable,
13840+
},
1379513841
};
13796-
1379713842
const bit_count = extra.type.scalarBits(self);
13798-
if (bit_count <= 64) {
13799-
const val = bigint.to(i64) catch unreachable;
13800-
const emit_val = if (tag == .positive_integer)
13801-
@shlWithOverflow(val, 1)[0]
13802-
else
13803-
(@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
13804-
try constants_block.writeAbbrev(Constants.Integer{ .value = @bitCast(emit_val) });
13805-
} else {
13806-
const word_count = std.mem.alignForward(u24, bit_count, 64) / 64;
13807-
try record.ensureUnusedCapacity(self.gpa, word_count);
13808-
const buffer: [*]u8 = @ptrCast(record.items.ptr);
13809-
bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
13810-
13811-
const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
13812-
for (signed_buffer[0..word_count], 0..) |val, i| {
13813-
signed_buffer[i] = if (val >= 0)
13814-
@shlWithOverflow(val, 1)[0]
13843+
const val: i64 = if (bit_count <= 64)
13844+
bigint.to(i64) catch unreachable
13845+
else if (bigint.to(u64)) |val|
13846+
@bitCast(val)
13847+
else |_| {
13848+
const limbs = try record.addManyAsSlice(
13849+
self.gpa,
13850+
std.math.divCeil(u24, bit_count, 64) catch unreachable,
13851+
);
13852+
bigint.writeTwosComplement(std.mem.sliceAsBytes(limbs), .little);
13853+
for (limbs) |*limb| {
13854+
const val = std.mem.littleToNative(i64, @bitCast(limb.*));
13855+
limb.* = @bitCast(if (val >= 0)
13856+
val << 1 | 0
1381513857
else
13816-
(@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
13858+
-%val << 1 | 1);
1381713859
}
13818-
13819-
try constants_block.writeUnabbrev(5, record.items.ptr[0..word_count]);
13820-
}
13860+
try constants_block.writeUnabbrev(5, record.items);
13861+
continue;
13862+
};
13863+
try constants_block.writeAbbrev(Constants.Integer{
13864+
.value = @bitCast(if (val >= 0)
13865+
val << 1 | 0
13866+
else
13867+
-%val << 1 | 1),
13868+
});
1382113869
},
1382213870
.half,
1382313871
.bfloat,
@@ -14186,6 +14234,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1418614234
self.metadata_items.items(.tag)[1..],
1418714235
self.metadata_items.items(.data)[1..],
1418814236
) |tag, data| {
14237+
record.clearRetainingCapacity();
1418914238
switch (tag) {
1419014239
.none => unreachable,
1419114240
.file => {
@@ -14333,77 +14382,60 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1433314382
.enumerator_signed_positive,
1433414383
.enumerator_signed_negative,
1433514384
=> |kind| {
14336-
const positive = switch (kind) {
14337-
.enumerator_unsigned,
14338-
.enumerator_signed_positive,
14339-
=> true,
14340-
.enumerator_signed_negative => false,
14341-
else => unreachable,
14342-
};
14343-
14344-
const unsigned = switch (kind) {
14345-
.enumerator_unsigned => true,
14346-
.enumerator_signed_positive,
14347-
.enumerator_signed_negative,
14348-
=> false,
14349-
else => unreachable,
14350-
};
14351-
1435214385
const extra = self.metadataExtraData(Metadata.Enumerator, data);
14353-
14354-
const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len];
14355-
1435614386
const bigint: std.math.big.int.Const = .{
14357-
.limbs = limbs,
14358-
.positive = positive,
14387+
.limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len],
14388+
.positive = switch (kind) {
14389+
.enumerator_unsigned,
14390+
.enumerator_signed_positive,
14391+
=> true,
14392+
.enumerator_signed_negative => false,
14393+
else => unreachable,
14394+
},
1435914395
};
14360-
14361-
if (extra.bit_width <= 64) {
14362-
const val = bigint.to(i64) catch unreachable;
14363-
const emit_val = if (positive)
14364-
@shlWithOverflow(val, 1)[0]
14365-
else
14366-
(@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
14367-
try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{
14368-
.flags = .{
14369-
.unsigned = unsigned,
14370-
},
14371-
.bit_width = extra.bit_width,
14372-
.name = extra.name,
14373-
.value = @bitCast(emit_val),
14374-
}, metadata_adapter);
14375-
} else {
14376-
const word_count = std.mem.alignForward(u32, extra.bit_width, 64) / 64;
14377-
try record.ensureUnusedCapacity(self.gpa, 3 + word_count);
14378-
14379-
const flags: MetadataBlock.Enumerator.Flags = .{
14380-
.unsigned = unsigned,
14381-
};
14382-
14383-
const FlagsInt = @typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?;
14384-
14385-
const flags_int: FlagsInt = @bitCast(flags);
14386-
14387-
record.appendAssumeCapacity(@intCast(flags_int));
14388-
record.appendAssumeCapacity(@intCast(extra.bit_width));
14396+
const flags: MetadataBlock.Enumerator.Flags = .{
14397+
.unsigned = switch (kind) {
14398+
.enumerator_unsigned => true,
14399+
.enumerator_signed_positive,
14400+
.enumerator_signed_negative,
14401+
=> false,
14402+
else => unreachable,
14403+
},
14404+
};
14405+
const val: i64 = if (bigint.to(i64)) |val|
14406+
val
14407+
else |_| if (bigint.to(u64)) |val|
14408+
@bitCast(val)
14409+
else |_| {
14410+
const limbs_len = std.math.divCeil(u32, extra.bit_width, 64) catch unreachable;
14411+
try record.ensureTotalCapacity(self.gpa, 3 + limbs_len);
14412+
record.appendAssumeCapacity(@as(
14413+
@typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?,
14414+
@bitCast(flags),
14415+
));
14416+
record.appendAssumeCapacity(extra.bit_width);
1438914417
record.appendAssumeCapacity(metadata_adapter.getMetadataStringIndex(extra.name));
14390-
14391-
const buffer: [*]u8 = @ptrCast(record.items.ptr);
14392-
bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
14393-
14394-
const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
14395-
for (signed_buffer[0..word_count], 0..) |val, i| {
14396-
signed_buffer[i] = if (val >= 0)
14397-
@shlWithOverflow(val, 1)[0]
14418+
const limbs = record.addManyAsSliceAssumeCapacity(limbs_len);
14419+
bigint.writeTwosComplement(std.mem.sliceAsBytes(limbs), .little);
14420+
for (limbs) |*limb| {
14421+
const val = std.mem.littleToNative(i64, @bitCast(limb.*));
14422+
limb.* = @bitCast(if (val >= 0)
14423+
val << 1 | 0
1439814424
else
14399-
(@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
14425+
-%val << 1 | 1);
1440014426
}
14401-
14402-
try metadata_block.writeUnabbrev(
14403-
MetadataBlock.Enumerator.id,
14404-
record.items.ptr[0..(3 + word_count)],
14405-
);
14406-
}
14427+
try metadata_block.writeUnabbrev(MetadataBlock.Enumerator.id, record.items);
14428+
continue;
14429+
};
14430+
try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{
14431+
.flags = flags,
14432+
.bit_width = extra.bit_width,
14433+
.name = extra.name,
14434+
.value = @bitCast(if (val >= 0)
14435+
val << 1 | 0
14436+
else
14437+
-%val << 1 | 1),
14438+
}, metadata_adapter);
1440714439
},
1440814440
.subrange => {
1440914441
const extra = self.metadataExtraData(Metadata.Subrange, data);
@@ -14491,7 +14523,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1449114523
}, metadata_adapter);
1449214524
},
1449314525
}
14494-
record.clearRetainingCapacity();
1449514526
}
1449614527

1449714528
// Write named metadata
@@ -14615,7 +14646,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1461514646
}
1461614647

1461714648
pub fn getOffsetValueIndex(adapter: @This(), value: Value) u32 {
14618-
return @subWithOverflow(adapter.offset(), adapter.getValueIndex(value))[0];
14649+
return adapter.offset() -% adapter.getValueIndex(value);
1461914650
}
1462014651

1462114652
pub fn getOffsetValueSignedIndex(adapter: @This(), value: Value) i32 {

0 commit comments

Comments
 (0)