InternPool: remove slice from byte aggregate keys

This deletes a ton of lookups and avoids many UAF bugs.

Closes #19485
This commit is contained in:
Jacob Young
2024-04-08 12:44:42 -04:00
parent 4cd92567e7
commit 7611d90ba0
24 changed files with 1038 additions and 952 deletions

View File

@@ -505,7 +505,7 @@ pub const Function = struct {
.never_inline,
=> |owner_decl| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{
@tagName(key),
fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)),
fmtIdent(zcu.declPtr(owner_decl).name.toSlice(&zcu.intern_pool)),
@intFromEnum(owner_decl),
}),
},
@@ -898,7 +898,7 @@ pub const DeclGen = struct {
},
},
.err => |err| try writer.print("zig_error_{}", .{
fmtIdent(ip.stringToSlice(err.name)),
fmtIdent(err.name.toSlice(ip)),
}),
.error_union => |error_union| {
const payload_ty = ty.errorUnionPayload(zcu);
@@ -1178,7 +1178,7 @@ pub const DeclGen = struct {
switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
.ty = field_ty.toIntern(),
.storage = .{ .u64 = bytes[field_index] },
.storage = .{ .u64 = bytes.at(field_index, ip) },
} }),
.elems => |elems| elems[field_index],
.repeated_elem => |elem| elem,
@@ -1212,7 +1212,7 @@ pub const DeclGen = struct {
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
.ty = field_ty.toIntern(),
.storage = .{ .u64 = bytes[field_index] },
.storage = .{ .u64 = bytes.at(field_index, ip) },
} }),
.elems => |elems| elems[field_index],
.repeated_elem => |elem| elem,
@@ -1258,7 +1258,7 @@ pub const DeclGen = struct {
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
.ty = field_ty.toIntern(),
.storage = .{ .u64 = bytes[field_index] },
.storage = .{ .u64 = bytes.at(field_index, ip) },
} }),
.elems => |elems| elems[field_index],
.repeated_elem => |elem| elem,
@@ -1299,7 +1299,7 @@ pub const DeclGen = struct {
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
.ty = field_ty.toIntern(),
.storage = .{ .u64 = bytes[field_index] },
.storage = .{ .u64 = bytes.at(field_index, ip) },
} }),
.elems => |elems| elems[field_index],
.repeated_elem => |elem| elem,
@@ -1392,7 +1392,7 @@ pub const DeclGen = struct {
try writer.writeAll(" .payload = {");
}
if (field_ty.hasRuntimeBits(zcu)) {
try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))});
try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))});
try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
try writer.writeByte(' ');
} else for (0..loaded_union.field_types.len) |this_field_index| {
@@ -1741,14 +1741,12 @@ pub const DeclGen = struct {
switch (name) {
.export_index => |export_index| mangled: {
const maybe_exports = zcu.decl_exports.get(fn_decl_index);
const external_name = ip.stringToSlice(
if (maybe_exports) |exports|
exports.items[export_index].opts.name
else if (fn_decl.isExtern(zcu))
fn_decl.name
else
break :mangled,
);
const external_name = (if (maybe_exports) |exports|
exports.items[export_index].opts.name
else if (fn_decl.isExtern(zcu))
fn_decl.name
else
break :mangled).toSlice(ip);
const is_mangled = isMangledIdent(external_name, true);
const is_export = export_index > 0;
if (is_mangled and is_export) {
@@ -1756,7 +1754,7 @@ pub const DeclGen = struct {
fmtIdent(external_name),
fmtStringLiteral(external_name, null),
fmtStringLiteral(
ip.stringToSlice(maybe_exports.?.items[0].opts.name),
maybe_exports.?.items[0].opts.name.toSlice(ip),
null,
),
});
@@ -1767,7 +1765,7 @@ pub const DeclGen = struct {
} else if (is_export) {
try w.print(" zig_export({s}, {s})", .{
fmtStringLiteral(
ip.stringToSlice(maybe_exports.?.items[0].opts.name),
maybe_exports.?.items[0].opts.name.toSlice(ip),
null,
),
fmtStringLiteral(external_name, null),
@@ -2075,12 +2073,12 @@ pub const DeclGen = struct {
.complete,
);
mangled: {
const external_name = zcu.intern_pool.stringToSlice(if (maybe_exports) |exports|
const external_name = (if (maybe_exports) |exports|
exports.items[0].opts.name
else if (variable.is_extern)
decl.name
else
break :mangled);
break :mangled).toSlice(&zcu.intern_pool);
if (isMangledIdent(external_name, true)) {
try fwd.print(" zig_mangled_{s}({ }, {s})", .{
@tagName(fwd_kind),
@@ -2094,15 +2092,16 @@ pub const DeclGen = struct {
fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {
const zcu = dg.zcu;
const ip = &zcu.intern_pool;
const decl = zcu.declPtr(decl_index);
if (zcu.decl_exports.get(decl_index)) |exports| {
try writer.print("{ }", .{
fmtIdent(zcu.intern_pool.stringToSlice(exports.items[export_index].opts.name)),
fmtIdent(exports.items[export_index].opts.name.toSlice(ip)),
});
} else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| {
try writer.print("{ }", .{
fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(extern_decl_index).name)),
fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)),
});
} else {
// MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
@@ -2226,7 +2225,7 @@ fn renderFwdDeclTypeName(
switch (fwd_decl.name) {
.anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),
.owner_decl => |owner_decl| try w.print("{}__{d}", .{
fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)),
fmtIdent(zcu.declPtr(owner_decl).name.toSlice(&zcu.intern_pool)),
@intFromEnum(owner_decl),
}),
}
@@ -2548,7 +2547,7 @@ pub fn genErrDecls(o: *Object) !void {
try writer.writeAll("enum {\n");
o.indent_writer.pushIndent();
for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| {
const name = ip.stringToSlice(name_nts);
const name = name_nts.toSlice(ip);
max_name_len = @max(name.len, max_name_len);
const err_val = try zcu.intern(.{ .err = .{
.ty = .anyerror_type,
@@ -2566,19 +2565,19 @@ pub fn genErrDecls(o: *Object) !void {
defer o.dg.gpa.free(name_buf);
@memcpy(name_buf[0..name_prefix.len], name_prefix);
for (zcu.global_error_set.keys()) |name_ip| {
const name = ip.stringToSlice(name_ip);
@memcpy(name_buf[name_prefix.len..][0..name.len], name);
const identifier = name_buf[0 .. name_prefix.len + name.len];
for (zcu.global_error_set.keys()) |name| {
const name_slice = name.toSlice(ip);
@memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice);
const identifier = name_buf[0 .. name_prefix.len + name_slice.len];
const name_ty = try zcu.arrayType(.{
.len = name.len,
.len = name_slice.len,
.child = .u8_type,
.sentinel = .zero_u8,
});
const name_val = try zcu.intern(.{ .aggregate = .{
.ty = name_ty.toIntern(),
.storage = .{ .bytes = name },
.storage = .{ .bytes = name.toString() },
} });
try writer.writeAll("static ");
@@ -2611,7 +2610,7 @@ pub fn genErrDecls(o: *Object) !void {
);
try writer.writeAll(" = {");
for (zcu.global_error_set.keys(), 0..) |name_nts, value| {
const name = ip.stringToSlice(name_nts);
const name = name_nts.toSlice(ip);
if (value != 0) try writer.writeByte(',');
try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
fmtIdent(name),
@@ -2659,7 +2658,7 @@ fn genExports(o: *Object) !void {
for (exports.items[1..]) |@"export"| {
try fwd.writeAll("zig_extern ");
if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
const export_name = ip.stringToSlice(@"export".opts.name);
const export_name = @"export".opts.name.toSlice(ip);
try o.dg.renderTypeAndName(
fwd,
decl.typeOf(zcu),
@@ -2672,11 +2671,11 @@ fn genExports(o: *Object) !void {
try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
fmtIdent(export_name),
fmtStringLiteral(export_name, null),
fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null),
});
} else {
try fwd.print(" zig_export({s}, {s})", .{
fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null),
fmtStringLiteral(export_name, null),
});
}
@@ -2706,17 +2705,18 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
try w.writeAll(") {\n switch (tag) {\n");
const tag_names = enum_ty.enumFields(zcu);
for (0..tag_names.len) |tag_index| {
const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]);
const tag_name = tag_names.get(ip)[tag_index];
const tag_name_len = tag_name.length(ip);
const tag_val = try zcu.enumValueFieldIndex(enum_ty, @intCast(tag_index));
const name_ty = try zcu.arrayType(.{
.len = tag_name.len,
.len = tag_name_len,
.child = .u8_type,
.sentinel = .zero_u8,
});
const name_val = try zcu.intern(.{ .aggregate = .{
.ty = name_ty.toIntern(),
.storage = .{ .bytes = tag_name },
.storage = .{ .bytes = tag_name.toString() },
} });
try w.print(" case {}: {{\n static ", .{
@@ -2729,7 +2729,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
try o.dg.renderType(w, name_slice_ty);
try w.print("){{{}, {}}};\n", .{
fmtIdent("name"),
try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name.len), .Other),
try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name_len), .Other),
});
try w.writeAll(" }\n");
@@ -2797,7 +2797,7 @@ pub fn genFunc(f: *Function) !void {
try o.indent_writer.insertNewline();
if (!is_global) try o.writer().writeAll("static ");
if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });
try o.writer().writeByte(' ');
@@ -2887,7 +2887,7 @@ pub fn genDecl(o: *Object) !void {
if (!is_global) try w.writeAll("static ");
if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
const decl_c_value = .{ .decl = decl_index };
try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete);
@@ -2920,7 +2920,7 @@ pub fn genDeclValue(
switch (o.dg.pass) {
.decl => |decl_index| {
if (zcu.decl_exports.get(decl_index)) |exports| {
const export_name = zcu.intern_pool.stringToSlice(exports.items[0].opts.name);
const export_name = exports.items[0].opts.name.toSlice(&zcu.intern_pool);
if (isMangledIdent(export_name, true)) {
try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{
fmtIdent(export_name), fmtStringLiteral(export_name, null),
@@ -2936,7 +2936,7 @@ pub fn genDeclValue(
const w = o.writer();
if (!is_global) try w.writeAll("static ");
if (zcu.intern_pool.stringToSliceUnwrap(@"linksection")) |s|
if (@"linksection".toSlice(&zcu.intern_pool)) |s|
try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
try w.writeAll(" = ");
@@ -5454,7 +5454,7 @@ fn fieldLocation(
.{ .byte_offset = loaded_struct.offsets.get(ip)[field_index] }
else
.{ .field = if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
.{ .identifier = ip.stringToSlice(field_name) }
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = field_index } },
.@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0)
@@ -5470,7 +5470,7 @@ fn fieldLocation(
.{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) }
else
.{ .field = if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name|
.{ .identifier = ip.stringToSlice(field_name) }
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = field_index } },
.union_type => {
@@ -5485,9 +5485,9 @@ fn fieldLocation(
.begin;
const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index];
return .{ .field = if (loaded_union.hasTag(ip))
.{ .payload_identifier = ip.stringToSlice(field_name) }
.{ .payload_identifier = field_name.toSlice(ip) }
else
.{ .identifier = ip.stringToSlice(field_name) } };
.{ .identifier = field_name.toSlice(ip) } };
},
.@"packed" => return .begin,
}
@@ -5643,7 +5643,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const loaded_struct = ip.loadStructType(struct_ty.toIntern());
switch (loaded_struct.layout) {
.auto, .@"extern" => break :field_name if (loaded_struct.fieldName(ip, extra.field_index).unwrap()) |field_name|
.{ .identifier = ip.stringToSlice(field_name) }
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = extra.field_index },
.@"packed" => {
@@ -5701,7 +5701,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
}
},
.anon_struct_type => |anon_struct_info| if (anon_struct_info.fieldName(ip, extra.field_index).unwrap()) |field_name|
.{ .identifier = ip.stringToSlice(field_name) }
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = extra.field_index },
.union_type => field_name: {
@@ -5710,9 +5710,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
.auto, .@"extern" => {
const name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index];
break :field_name if (loaded_union.hasTag(ip))
.{ .payload_identifier = ip.stringToSlice(name) }
.{ .payload_identifier = name.toSlice(ip) }
else
.{ .identifier = ip.stringToSlice(name) };
.{ .identifier = name.toSlice(ip) };
},
.@"packed" => {
const operand_lval = if (struct_byval == .constant) blk: {
@@ -7062,7 +7062,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const a = try Assignment.start(f, writer, field_ty);
try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
.{ .identifier = ip.stringToSlice(field_name) }
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = field_index });
try a.assign(f, writer);
@@ -7142,7 +7142,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const a = try Assignment.start(f, writer, field_ty);
try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name|
.{ .identifier = ip.stringToSlice(field_name) }
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = field_index });
try a.assign(f, writer);
@@ -7190,8 +7190,8 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))});
try a.end(f, writer);
}
break :field .{ .payload_identifier = ip.stringToSlice(field_name) };
} else .{ .identifier = ip.stringToSlice(field_name) };
break :field .{ .payload_identifier = field_name.toSlice(ip) };
} else .{ .identifier = field_name.toSlice(ip) };
const a = try Assignment.start(f, writer, payload_ty);
try f.writeCValueMember(writer, local, field);

View File

@@ -1465,7 +1465,7 @@ pub const Pool = struct {
},
},
.array_type => |array_info| {
const len = array_info.len + @intFromBool(array_info.sentinel != .none);
const len = array_info.lenIncludingSentinel();
if (len == 0) return .{ .index = .void };
const elem_type = Type.fromInterned(array_info.child);
const elem_ctype = try pool.fromType(
@@ -1479,7 +1479,7 @@ pub const Pool = struct {
if (elem_ctype.index == .void) return .{ .index = .void };
const array_ctype = try pool.getArray(allocator, .{
.elem_ctype = elem_ctype,
.len = array_info.len + @intFromBool(array_info.sentinel != .none),
.len = len,
});
if (!kind.isParameter()) return array_ctype;
var fields = [_]Info.Field{
@@ -1625,7 +1625,7 @@ pub const Pool = struct {
if (field_ctype.index == .void) continue;
const field_name = if (loaded_struct.fieldName(ip, field_index)
.unwrap()) |field_name|
try pool.string(allocator, ip.stringToSlice(field_name))
try pool.string(allocator, field_name.toSlice(ip))
else
try pool.fmt(allocator, "f{d}", .{field_index});
const field_alignas = AlignAs.fromAlignment(.{
@@ -1685,7 +1685,7 @@ pub const Pool = struct {
if (field_ctype.index == .void) continue;
const field_name = if (anon_struct_info.fieldName(ip, @intCast(field_index))
.unwrap()) |field_name|
try pool.string(allocator, ip.stringToSlice(field_name))
try pool.string(allocator, field_name.toSlice(ip))
else
try pool.fmt(allocator, "f{d}", .{field_index});
pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{
@@ -1766,7 +1766,7 @@ pub const Pool = struct {
if (field_ctype.index == .void) continue;
const field_name = try pool.string(
allocator,
ip.stringToSlice(loaded_tag.names.get(ip)[field_index]),
loaded_tag.names.get(ip)[field_index].toSlice(ip),
);
const field_alignas = AlignAs.fromAlignment(.{
.@"align" = loaded_union.fieldAlign(ip, @intCast(field_index)),

View File

@@ -1011,7 +1011,7 @@ pub const Object = struct {
llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
const name_string = try o.builder.stringNull(mod.intern_pool.stringToSlice(name));
const name_string = try o.builder.stringNull(name.toSlice(&mod.intern_pool));
const name_init = try o.builder.stringConst(name_string);
const name_variable_index =
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
@@ -1086,7 +1086,7 @@ pub const Object = struct {
for (object.extern_collisions.keys()) |decl_index| {
const global = object.decl_map.get(decl_index) orelse continue;
// Same logic as below but for externs instead of exports.
const decl_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
const decl_name = object.builder.strtabStringIfExists(mod.declPtr(decl_index).name.toSlice(&mod.intern_pool)) orelse continue;
const other_global = object.builder.getGlobal(decl_name) orelse continue;
if (other_global.toConst().getBase(&object.builder) ==
global.toConst().getBase(&object.builder)) continue;
@@ -1116,7 +1116,7 @@ pub const Object = struct {
for (export_list) |exp| {
// Detect if the LLVM global has already been created as an extern. In such
// case, we need to replace all uses of it with this exported global.
const exp_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
const exp_name = object.builder.strtabStringIfExists(exp.opts.name.toSlice(&mod.intern_pool)) orelse continue;
const other_global = object.builder.getGlobal(exp_name) orelse continue;
if (other_global.toConst().getBase(&object.builder) == global_base) continue;
@@ -1442,7 +1442,7 @@ pub const Object = struct {
} }, &o.builder);
}
if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
if (decl.@"linksection".toSlice(ip)) |section|
function_index.setSection(try o.builder.string(section), &o.builder);
var deinit_wip = true;
@@ -1662,7 +1662,7 @@ pub const Object = struct {
const subprogram = try o.builder.debugSubprogram(
file,
try o.builder.metadataString(ip.stringToSlice(decl.name)),
try o.builder.metadataString(decl.name.toSlice(ip)),
try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder)),
line_number,
line_number + func.lbrace_line,
@@ -1752,6 +1752,7 @@ pub const Object = struct {
.value => |val| return updateExportedValue(self, mod, val, exports),
};
const gpa = mod.gpa;
const ip = &mod.intern_pool;
// If the module does not already have the function, we ignore this function call
// because we call `updateExports` at the end of `updateFunc` and `updateDecl`.
const global_index = self.decl_map.get(decl_index) orelse return;
@@ -1759,17 +1760,14 @@ pub const Object = struct {
const comp = mod.comp;
if (decl.isExtern(mod)) {
const decl_name = decl_name: {
const decl_name = mod.intern_pool.stringToSlice(decl.name);
if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) {
if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
if (decl.getOwnedExternFunc(mod).?.lib_name.toSlice(ip)) |lib_name| {
if (!std.mem.eql(u8, lib_name, "c")) {
break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name });
break :decl_name try self.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name });
}
}
}
break :decl_name try self.builder.strtabString(decl_name);
break :decl_name try self.builder.strtabString(decl.name.toSlice(ip));
};
if (self.builder.getGlobal(decl_name)) |other_global| {
@@ -1792,9 +1790,7 @@ pub const Object = struct {
if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
}
} else if (exports.len != 0) {
const main_exp_name = try self.builder.strtabString(
mod.intern_pool.stringToSlice(exports[0].opts.name),
);
const main_exp_name = try self.builder.strtabString(exports[0].opts.name.toSlice(ip));
try global_index.rename(main_exp_name, &self.builder);
if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
@@ -1803,9 +1799,7 @@ pub const Object = struct {
return updateExportedGlobal(self, mod, global_index, exports);
} else {
const fqn = try self.builder.strtabString(
mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)),
);
const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(mod)).toSlice(ip));
try global_index.rename(fqn, &self.builder);
global_index.setLinkage(.internal, &self.builder);
if (comp.config.dll_export_fns)
@@ -1832,9 +1826,8 @@ pub const Object = struct {
exports: []const *Module.Export,
) link.File.UpdateExportsError!void {
const gpa = mod.gpa;
const main_exp_name = try o.builder.strtabString(
mod.intern_pool.stringToSlice(exports[0].opts.name),
);
const ip = &mod.intern_pool;
const main_exp_name = try o.builder.strtabString(exports[0].opts.name.toSlice(ip));
const global_index = i: {
const gop = try o.anon_decl_map.getOrPut(gpa, exported_value);
if (gop.found_existing) {
@@ -1845,7 +1838,7 @@ pub const Object = struct {
const llvm_addr_space = toLlvmAddressSpace(.generic, o.target);
const variable_index = try o.builder.addVariable(
main_exp_name,
try o.lowerType(Type.fromInterned(mod.intern_pool.typeOf(exported_value))),
try o.lowerType(Type.fromInterned(ip.typeOf(exported_value))),
llvm_addr_space,
);
const global_index = variable_index.ptrConst(&o.builder).global;
@@ -1867,8 +1860,9 @@ pub const Object = struct {
global_index: Builder.Global.Index,
exports: []const *Module.Export,
) link.File.UpdateExportsError!void {
global_index.setUnnamedAddr(.default, &o.builder);
const comp = mod.comp;
const ip = &mod.intern_pool;
global_index.setUnnamedAddr(.default, &o.builder);
if (comp.config.dll_export_fns)
global_index.setDllStorageClass(.dllexport, &o.builder);
global_index.setLinkage(switch (exports[0].opts.linkage) {
@@ -1882,7 +1876,7 @@ pub const Object = struct {
.hidden => .hidden,
.protected => .protected,
}, &o.builder);
if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section|
if (exports[0].opts.section.toSlice(ip)) |section|
switch (global_index.ptrConst(&o.builder).kind) {
.variable => |impl_index| impl_index.setSection(
try o.builder.string(section),
@@ -1900,7 +1894,7 @@ pub const Object = struct {
// Until then we iterate over existing aliases and make them point
// to the correct decl, or otherwise add a new alias. Old aliases are leaked.
for (exports[1..]) |exp| {
const exp_name = try o.builder.strtabString(mod.intern_pool.stringToSlice(exp.opts.name));
const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));
if (o.builder.getGlobal(exp_name)) |global| {
switch (global.ptrConst(&o.builder).kind) {
.alias => |alias| {
@@ -2013,7 +2007,7 @@ pub const Object = struct {
std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
enumerators[i] = try o.builder.debugEnumerator(
try o.builder.metadataString(ip.stringToSlice(field_name_ip)),
try o.builder.metadataString(field_name_ip.toSlice(ip)),
int_info.signedness == .unsigned,
int_info.bits,
bigint,
@@ -2473,7 +2467,7 @@ pub const Object = struct {
offset = field_offset + field_size;
const field_name = if (tuple.names.len != 0)
ip.stringToSlice(tuple.names.get(ip)[i])
tuple.names.get(ip)[i].toSlice(ip)
else
try std.fmt.allocPrintZ(gpa, "{d}", .{i});
defer if (tuple.names.len == 0) gpa.free(field_name);
@@ -2557,10 +2551,10 @@ pub const Object = struct {
const field_offset = ty.structFieldOffset(field_index, mod);
const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});
try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls);
fields.appendAssumeCapacity(try o.builder.debugMemberType(
try o.builder.metadataString(ip.stringToSlice(field_name)),
try o.builder.metadataString(field_name.toSlice(ip)),
.none, // File
debug_fwd_ref,
0, // Line
@@ -2655,7 +2649,7 @@ pub const Object = struct {
const field_name = tag_type.names.get(ip)[field_index];
fields.appendAssumeCapacity(try o.builder.debugMemberType(
try o.builder.metadataString(ip.stringToSlice(field_name)),
try o.builder.metadataString(field_name.toSlice(ip)),
.none, // File
debug_union_fwd_ref,
0, // Line
@@ -2827,7 +2821,7 @@ pub const Object = struct {
const mod = o.module;
const decl = mod.declPtr(decl_index);
return o.builder.debugStructType(
try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name
try o.builder.metadataString(decl.name.toSlice(&mod.intern_pool)), // TODO use fully qualified name
try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope),
try o.namespaceToDebugScope(decl.src_namespace),
decl.src_line + 1,
@@ -2844,11 +2838,11 @@ pub const Object = struct {
const std_mod = mod.std_mod;
const std_file = (mod.importPkg(std_mod) catch unreachable).file;
const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin");
const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin", .no_embedded_nulls);
const std_namespace = mod.namespacePtr(mod.declPtr(std_file.root_decl.unwrap().?).src_namespace);
const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Module.DeclAdapter{ .zcu = mod }).?;
const stack_trace_str = try mod.intern_pool.getOrPutString(mod.gpa, "StackTrace");
const stack_trace_str = try mod.intern_pool.getOrPutString(mod.gpa, "StackTrace", .no_embedded_nulls);
// buffer is only used for int_type, `builtin` is a struct.
const builtin_ty = mod.declPtr(builtin_decl).val.toType();
const builtin_namespace = mod.namespacePtrUnwrap(builtin_ty.getNamespaceIndex(mod)).?;
@@ -2892,10 +2886,10 @@ pub const Object = struct {
const is_extern = decl.isExtern(zcu);
const function_index = try o.builder.addFunction(
try o.lowerType(zig_fn_type),
try o.builder.strtabString(ip.stringToSlice(if (is_extern)
try o.builder.strtabString((if (is_extern)
decl.name
else
try decl.fullyQualifiedName(zcu))),
try decl.fullyQualifiedName(zcu)).toSlice(ip)),
toLlvmAddressSpace(decl.@"addrspace", target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@@ -2910,9 +2904,9 @@ pub const Object = struct {
if (target.isWasm()) {
try attributes.addFnAttr(.{ .string = .{
.kind = try o.builder.string("wasm-import-name"),
.value = try o.builder.string(ip.stringToSlice(decl.name)),
.value = try o.builder.string(decl.name.toSlice(ip)),
} }, &o.builder);
if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(zcu).?.lib_name)) |lib_name| {
if (decl.getOwnedExternFunc(zcu).?.lib_name.toSlice(ip)) |lib_name| {
if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
.kind = try o.builder.string("wasm-import-module"),
.value = try o.builder.string(lib_name),
@@ -3108,9 +3102,10 @@ pub const Object = struct {
const is_extern = decl.isExtern(mod);
const variable_index = try o.builder.addVariable(
try o.builder.strtabString(mod.intern_pool.stringToSlice(
if (is_extern) decl.name else try decl.fullyQualifiedName(mod),
)),
try o.builder.strtabString((if (is_extern)
decl.name
else
try decl.fullyQualifiedName(mod)).toSlice(&mod.intern_pool)),
try o.lowerType(decl.typeOf(mod)),
toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
);
@@ -3258,7 +3253,7 @@ pub const Object = struct {
};
},
.array_type => |array_type| o.builder.arrayType(
array_type.len + @intFromBool(array_type.sentinel != .none),
array_type.lenIncludingSentinel(),
try o.lowerType(Type.fromInterned(array_type.child)),
),
.vector_type => |vector_type| o.builder.vectorType(
@@ -3335,9 +3330,7 @@ pub const Object = struct {
return int_ty;
}
const name = try o.builder.string(ip.stringToSlice(
try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(mod),
));
const fqn = try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(mod);
var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
defer llvm_field_types.deinit(o.gpa);
@@ -3402,7 +3395,7 @@ pub const Object = struct {
);
}
const ty = try o.builder.opaqueType(name);
const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@@ -3491,9 +3484,7 @@ pub const Object = struct {
return enum_tag_ty;
}
const name = try o.builder.string(ip.stringToSlice(
try mod.declPtr(union_obj.decl).fullyQualifiedName(mod),
));
const fqn = try mod.declPtr(union_obj.decl).fullyQualifiedName(mod);
const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);
const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);
@@ -3513,7 +3504,7 @@ pub const Object = struct {
};
if (layout.tag_size == 0) {
const ty = try o.builder.opaqueType(name);
const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@@ -3541,7 +3532,7 @@ pub const Object = struct {
llvm_fields_len += 1;
}
const ty = try o.builder.opaqueType(name);
const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@@ -3554,8 +3545,8 @@ pub const Object = struct {
const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
if (!gop.found_existing) {
const decl = mod.declPtr(ip.loadOpaqueType(t.toIntern()).decl);
const name = try o.builder.string(ip.stringToSlice(try decl.fullyQualifiedName(mod)));
gop.value_ptr.* = try o.builder.opaqueType(name);
const fqn = try decl.fullyQualifiedName(mod);
gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
}
return gop.value_ptr.*;
},
@@ -3859,7 +3850,9 @@ pub const Object = struct {
},
.aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
.array_type => |array_type| switch (aggregate.storage) {
.bytes => |bytes| try o.builder.stringConst(try o.builder.string(bytes)),
.bytes => |bytes| try o.builder.stringConst(try o.builder.string(
bytes.toSlice(array_type.lenIncludingSentinel(), ip),
)),
.elems => |elems| {
const array_ty = try o.lowerType(ty);
const elem_ty = array_ty.childType(&o.builder);
@@ -3892,8 +3885,7 @@ pub const Object = struct {
},
.repeated_elem => |elem| {
const len: usize = @intCast(array_type.len);
const len_including_sentinel: usize =
@intCast(len + @intFromBool(array_type.sentinel != .none));
const len_including_sentinel: usize = @intCast(array_type.lenIncludingSentinel());
const array_ty = try o.lowerType(ty);
const elem_ty = array_ty.childType(&o.builder);
@@ -3942,7 +3934,7 @@ pub const Object = struct {
defer allocator.free(vals);
switch (aggregate.storage) {
.bytes => |bytes| for (vals, bytes) |*result_val, byte| {
.bytes => |bytes| for (vals, bytes.toSlice(vector_type.len, ip)) |*result_val, byte| {
result_val.* = try o.builder.intConst(.i8, byte);
},
.elems => |elems| for (vals, elems) |*result_val, elem| {
@@ -4633,7 +4625,7 @@ pub const Object = struct {
defer wip_switch.finish(&wip);
for (0..enum_type.names.len) |field_index| {
const name = try o.builder.stringNull(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
const name = try o.builder.stringNull(enum_type.names.get(ip)[field_index].toSlice(ip));
const name_init = try o.builder.stringConst(name);
const name_variable_index =
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
@@ -4693,6 +4685,7 @@ pub const DeclGen = struct {
fn genDecl(dg: *DeclGen) !void {
const o = dg.object;
const zcu = o.module;
const ip = &zcu.intern_pool;
const decl = dg.decl;
const decl_index = dg.decl_index;
assert(decl.has_tv);
@@ -4705,7 +4698,7 @@ pub const DeclGen = struct {
decl.getAlignment(zcu).toLlvm(),
&o.builder,
);
if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
if (decl.@"linksection".toSlice(ip)) |section|
variable_index.setSection(try o.builder.string(section), &o.builder);
assert(decl.has_tv);
const init_val = if (decl.val.getVariable(zcu)) |decl_var| decl_var.init else init_val: {
@@ -4728,7 +4721,7 @@ pub const DeclGen = struct {
const debug_file = try o.getDebugFile(namespace.file_scope);
const debug_global_var = try o.builder.debugGlobalVar(
try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)), // Name
try o.builder.metadataString(decl.name.toSlice(ip)), // Name
try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name
debug_file, // File
debug_file, // Scope
@@ -5156,8 +5149,8 @@ pub const FuncGen = struct {
self.scope = try o.builder.debugSubprogram(
self.file,
try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)),
try o.builder.metadataString(zcu.intern_pool.stringToSlice(fqn)),
try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)),
try o.builder.metadataString(fqn.toSlice(&zcu.intern_pool)),
line_number,
line_number + func.lbrace_line,
try o.lowerDebugType(fn_ty),

View File

@@ -1028,39 +1028,30 @@ const DeclGen = struct {
inline .array_type, .vector_type => |array_type, tag| {
const elem_ty = Type.fromInterned(array_type.child);
const constituents = try self.gpa.alloc(IdRef, @as(u32, @intCast(ty.arrayLenIncludingSentinel(mod))));
const constituents = try self.gpa.alloc(IdRef, @intCast(ty.arrayLenIncludingSentinel(mod)));
defer self.gpa.free(constituents);
switch (aggregate.storage) {
.bytes => |bytes| {
// TODO: This is really space inefficient, perhaps there is a better
// way to do it?
for (bytes, 0..) |byte, i| {
constituents[i] = try self.constInt(elem_ty, byte, .indirect);
for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| {
constituent.* = try self.constInt(elem_ty, byte, .indirect);
}
},
.elems => |elems| {
for (0..@as(usize, @intCast(array_type.len))) |i| {
constituents[i] = try self.constant(elem_ty, Value.fromInterned(elems[i]), .indirect);
for (constituents, elems) |*constituent, elem| {
constituent.* = try self.constant(elem_ty, Value.fromInterned(elem), .indirect);
}
},
.repeated_elem => |elem| {
const val_id = try self.constant(elem_ty, Value.fromInterned(elem), .indirect);
for (0..@as(usize, @intCast(array_type.len))) |i| {
constituents[i] = val_id;
}
@memset(constituents, try self.constant(elem_ty, Value.fromInterned(elem), .indirect));
},
}
switch (tag) {
inline .array_type => {
if (array_type.sentinel != .none) {
const sentinel = Value.fromInterned(array_type.sentinel);
constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect);
}
return self.constructArray(ty, constituents);
},
inline .vector_type => return self.constructVector(ty, constituents),
.array_type => return self.constructArray(ty, constituents),
.vector_type => return self.constructVector(ty, constituents),
else => unreachable,
}
},
@@ -1683,9 +1674,9 @@ const DeclGen = struct {
}
const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index});
try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index}, .no_embedded_nulls);
try member_types.append(try self.resolveType(field_ty, .indirect));
try member_names.append(ip.stringToSlice(field_name));
try member_names.append(field_name.toSlice(ip));
}
const result_id = try self.spv.structType(member_types.items, member_names.items);
@@ -2123,12 +2114,12 @@ const DeclGen = struct {
// Append the actual code into the functions section.
try self.spv.addFunction(spv_decl_index, self.func);
const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module));
try self.spv.debugName(result_id, fqn);
const fqn = try decl.fullyQualifiedName(self.module);
try self.spv.debugName(result_id, fqn.toSlice(ip));
// Temporarily generate a test kernel declaration if this is a test function.
if (self.module.test_functions.contains(self.decl_index)) {
try self.generateTestEntryPoint(fqn, spv_decl_index);
try self.generateTestEntryPoint(fqn.toSlice(ip), spv_decl_index);
}
},
.global => {
@@ -2152,8 +2143,8 @@ const DeclGen = struct {
.storage_class = final_storage_class,
});
const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module));
try self.spv.debugName(result_id, fqn);
const fqn = try decl.fullyQualifiedName(self.module);
try self.spv.debugName(result_id, fqn.toSlice(ip));
try self.spv.declareDeclDeps(spv_decl_index, &.{});
},
.invocation_global => {
@@ -2197,8 +2188,8 @@ const DeclGen = struct {
try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
try self.spv.addFunction(spv_decl_index, self.func);
const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module));
try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn});
const fqn = try decl.fullyQualifiedName(self.module);
try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{fqn.fmt(ip)});
try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
.id_result_type = ptr_ty_id,