aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorMatthew Lugg <mlugg@mlugg.co.uk>2024-07-11 23:27:13 +0100
committerGitHub <noreply@github.com>2024-07-11 23:27:13 +0100
commit80d7e260d78400b841f15e3350473650b87931a5 (patch)
tree3035bae743da24cbe1d5046469fea0a5542a8829 /src/codegen
parent45be80364659332807b527670514332a4b835f84 (diff)
parent77810f288216ef3e35f3d0df4a04351297560a5e (diff)
downloadzig-80d7e260d78400b841f15e3350473650b87931a5.tar.gz
zig-80d7e260d78400b841f15e3350473650b87931a5.zip
Merge pull request #20570 from jacobly0/fix-races
InternPool: fix more races blocking a separate codegen/linker thread
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig35
-rw-r--r--src/codegen/llvm.zig72
-rw-r--r--src/codegen/spirv.zig13
3 files changed, 53 insertions, 67 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 2fa8a98cbb..60b07f0e3f 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -2194,13 +2194,9 @@ pub const DeclGen = struct {
}) else {
// MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
// expand to 3x the length of its input, but let's cut it off at a much shorter limit.
- var name: [100]u8 = undefined;
- var name_stream = std.io.fixedBufferStream(&name);
- decl.renderFullyQualifiedName(zcu, name_stream.writer()) catch |err| switch (err) {
- error.NoSpaceLeft => {},
- };
+ const fqn_slice = decl.fqn.toSlice(ip);
try writer.print("{}__{d}", .{
- fmtIdent(name_stream.getWritten()),
+ fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),
@intFromEnum(decl_index),
});
}
@@ -2587,11 +2583,9 @@ pub fn genTypeDecl(
try writer.writeByte(';');
const owner_decl = zcu.declPtr(owner_decl_index);
const owner_mod = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu).mod;
- if (!owner_mod.strip) {
- try writer.writeAll(" /* ");
- try owner_decl.renderFullyQualifiedName(zcu, writer);
- try writer.writeAll(" */");
- }
+ if (!owner_mod.strip) try writer.print(" /* {} */", .{
+ owner_decl.fqn.fmt(&zcu.intern_pool),
+ });
try writer.writeByte('\n');
},
},
@@ -2628,10 +2622,11 @@ pub fn genErrDecls(o: *Object) !void {
var max_name_len: usize = 0;
// do not generate an invalid empty enum when the global error set is empty
- if (zcu.global_error_set.keys().len > 1) {
+ const names = ip.global_error_set.getNamesFromMainThread();
+ if (names.len > 0) {
try writer.writeAll("enum {\n");
o.indent_writer.pushIndent();
- for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| {
+ for (names, 1..) |name_nts, value| {
const name = name_nts.toSlice(ip);
max_name_len = @max(name.len, max_name_len);
const err_val = try pt.intern(.{ .err = .{
@@ -2650,7 +2645,7 @@ 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| {
+ for (names) |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];
@@ -2680,7 +2675,7 @@ pub fn genErrDecls(o: *Object) !void {
}
const name_array_ty = try pt.arrayType(.{
- .len = zcu.global_error_set.count(),
+ .len = 1 + names.len,
.child = .slice_const_u8_sentinel_0_type,
});
@@ -2694,9 +2689,9 @@ pub fn genErrDecls(o: *Object) !void {
.complete,
);
try writer.writeAll(" = {");
- for (zcu.global_error_set.keys(), 0..) |name_nts, value| {
+ for (names, 1..) |name_nts, val| {
const name = name_nts.toSlice(ip);
- if (value != 0) try writer.writeByte(',');
+ if (val > 1) try writer.writeAll(", ");
try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
fmtIdent(name),
try o.dg.fmtIntLiteral(try pt.intValue(Type.usize, name.len), .StaticInitializer),
@@ -4563,9 +4558,7 @@ 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("/* inline:");
- try owner_decl.renderFullyQualifiedName(zcu, writer);
- try writer.writeAll(" */\n");
+ try writer.print("/* inline:{} */\n", .{owner_decl.fqn.fmt(&zcu.intern_pool)});
return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
}
@@ -6881,7 +6874,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
try writer.writeAll(" = zig_errorName[");
try f.writeCValue(writer, operand, .Other);
- try writer.writeAll("];\n");
+ try writer.writeAll(" - 1];\n");
return local;
}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 0f13c9fd9b..abc6a9dc9d 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1036,20 +1036,21 @@ pub const Object = struct {
const pt = o.pt;
const mod = pt.zcu;
+ const ip = &mod.intern_pool;
- const error_name_list = mod.global_error_set.keys();
- const llvm_errors = try mod.gpa.alloc(Builder.Constant, error_name_list.len);
+ const error_name_list = ip.global_error_set.getNamesFromMainThread();
+ const llvm_errors = try mod.gpa.alloc(Builder.Constant, 1 + error_name_list.len);
defer mod.gpa.free(llvm_errors);
// TODO: Address space
const slice_ty = Type.slice_const_u8_sentinel_0;
const llvm_usize_ty = try o.lowerType(Type.usize);
const llvm_slice_ty = try o.lowerType(slice_ty);
- const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);
+ const llvm_table_ty = try o.builder.arrayType(1 + error_name_list.len, llvm_slice_ty);
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(name.toSlice(&mod.intern_pool));
+ for (llvm_errors[1..], error_name_list) |*llvm_error, name| {
+ const name_string = try o.builder.stringNull(name.toSlice(ip));
const name_init = try o.builder.stringConst(name_string);
const name_variable_index =
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
@@ -1085,7 +1086,7 @@ pub const Object = struct {
// If there is no such function in the module, it means the source code does not need it.
const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return;
const llvm_fn = o.builder.getGlobal(name) orelse return;
- const errors_len = o.pt.zcu.global_error_set.count();
+ const errors_len = o.pt.zcu.intern_pool.global_error_set.mutate.list.len;
var wip = try Builder.WipFunction.init(&o.builder, .{
.function = llvm_fn.ptrConst(&o.builder).kind.function,
@@ -1096,12 +1097,12 @@ pub const Object = struct {
// Example source of the following LLVM IR:
// fn __zig_lt_errors_len(index: u16) bool {
- // return index < total_errors_len;
+ // return index <= total_errors_len;
// }
const lhs = wip.arg(0);
const rhs = try o.builder.intValue(try o.errorIntType(), errors_len);
- const is_lt = try wip.icmp(.ult, lhs, rhs, "");
+ const is_lt = try wip.icmp(.ule, lhs, rhs, "");
_ = try wip.ret(is_lt);
try wip.finish();
}
@@ -1744,7 +1745,7 @@ pub const Object = struct {
if (export_indices.len != 0) {
return updateExportedGlobal(self, zcu, global_index, export_indices);
} else {
- const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(pt)).toSlice(ip));
+ const fqn = try self.builder.strtabString(decl.fqn.toSlice(ip));
try global_index.rename(fqn, &self.builder);
global_index.setLinkage(.internal, &self.builder);
if (comp.config.dll_export_fns)
@@ -2811,7 +2812,7 @@ pub const Object = struct {
const zcu = pt.zcu;
const std_mod = zcu.std_mod;
- const std_file_imported = zcu.importPkg(std_mod) catch unreachable;
+ const std_file_imported = pt.importPkg(std_mod) catch unreachable;
const builtin_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "builtin", .no_embedded_nulls);
const std_file_root_decl = zcu.fileRootDecl(std_file_imported.file_index);
@@ -2863,10 +2864,7 @@ 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((if (is_extern)
- decl.name
- else
- try decl.fullyQualifiedName(pt)).toSlice(ip)),
+ try o.builder.strtabString((if (is_extern) decl.name else decl.fqn).toSlice(ip)),
toLlvmAddressSpace(decl.@"addrspace", target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@@ -3077,14 +3075,12 @@ pub const Object = struct {
const pt = o.pt;
const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
const decl = zcu.declPtr(decl_index);
const is_extern = decl.isExtern(zcu);
const variable_index = try o.builder.addVariable(
- try o.builder.strtabString((if (is_extern)
- decl.name
- else
- try decl.fullyQualifiedName(pt)).toSlice(&zcu.intern_pool)),
+ try o.builder.strtabString((if (is_extern) decl.name else decl.fqn).toSlice(ip)),
try o.lowerType(decl.typeOf(zcu)),
toLlvmGlobalAddressSpace(decl.@"addrspace", zcu.getTarget()),
);
@@ -3312,7 +3308,7 @@ pub const Object = struct {
return int_ty;
}
- const fqn = try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(pt);
+ const decl = mod.declPtr(struct_type.decl.unwrap().?);
var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
defer llvm_field_types.deinit(o.gpa);
@@ -3377,7 +3373,7 @@ pub const Object = struct {
);
}
- const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
+ const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@@ -3466,7 +3462,7 @@ pub const Object = struct {
return enum_tag_ty;
}
- const fqn = try mod.declPtr(union_obj.decl).fullyQualifiedName(pt);
+ const decl = mod.declPtr(union_obj.decl);
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);
@@ -3486,7 +3482,7 @@ pub const Object = struct {
};
if (layout.tag_size == 0) {
- const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
+ const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@@ -3514,7 +3510,7 @@ pub const Object = struct {
llvm_fields_len += 1;
}
- const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
+ const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@@ -3527,8 +3523,7 @@ 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 fqn = try decl.fullyQualifiedName(pt);
- gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
+ gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
}
return gop.value_ptr.*;
},
@@ -3826,7 +3821,7 @@ pub const Object = struct {
return lowerBigInt(o, ty, bigint);
},
.err => |err| {
- const int = try mod.getErrorValue(err.name);
+ const int = try pt.getErrorValue(err.name);
const llvm_int = try o.builder.intConst(try o.errorIntType(), int);
return llvm_int;
},
@@ -4587,11 +4582,11 @@ pub const Object = struct {
const usize_ty = try o.lowerType(Type.usize);
const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
- const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(pt);
+ const decl = zcu.declPtr(enum_type.decl);
const target = zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
- try o.builder.strtabStringFmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
+ try o.builder.strtabStringFmt("__zig_tag_name_{}", .{decl.fqn.fmt(ip)}),
toLlvmAddressSpace(.generic, target),
);
@@ -5175,8 +5170,6 @@ pub const FuncGen = struct {
const line_number = decl.navSrcLine(zcu) + 1;
self.inlined = self.wip.debug_location;
- const fqn = try decl.fullyQualifiedName(pt);
-
const fn_ty = try pt.funcType(.{
.param_types = &.{},
.return_type = .void_type,
@@ -5185,7 +5178,7 @@ pub const FuncGen = struct {
self.scope = try o.builder.debugSubprogram(
self.file,
try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)),
- try o.builder.metadataString(fqn.toSlice(&zcu.intern_pool)),
+ try o.builder.metadataString(decl.fqn.toSlice(&zcu.intern_pool)),
line_number,
line_number + func.lbrace_line,
try o.lowerDebugType(fn_ty),
@@ -8867,19 +8860,21 @@ pub const FuncGen = struct {
self.arg_index += 1;
// llvm does not support debug info for naked function arguments
- if (self.wip.strip or self.is_naked) return arg_val;
+ if (self.is_naked) return arg_val;
const inst_ty = self.typeOfIndex(inst);
if (needDbgVarWorkaround(o)) return arg_val;
- const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
+ const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
+ if (name == .none) return arg_val;
+
const func_index = self.dg.decl.getOwnedFunctionIndex();
const func = mod.funcInfo(func_index);
const lbrace_line = mod.declPtr(func.owner_decl).navSrcLine(mod) + func.lbrace_line + 1;
const lbrace_col = func.lbrace_column + 1;
const debug_parameter = try o.builder.debugParameter(
- try o.builder.metadataString(mod.getParamName(func_index, src_index)),
+ try o.builder.metadataString(self.air.nullTerminatedString(@intFromEnum(name))),
self.file,
self.scope,
lbrace_line,
@@ -9664,7 +9659,7 @@ pub const FuncGen = struct {
defer wip_switch.finish(&self.wip);
for (0..names.len) |name_index| {
- const err_int = mod.global_error_set.getIndex(names.get(ip)[name_index]).?;
+ const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
}
@@ -9702,18 +9697,19 @@ pub const FuncGen = struct {
const o = self.dg.object;
const pt = o.pt;
const zcu = pt.zcu;
- const enum_type = zcu.intern_pool.loadEnumType(enum_ty.toIntern());
+ const ip = &zcu.intern_pool;
+ const enum_type = ip.loadEnumType(enum_ty.toIntern());
// TODO: detect when the type changes and re-emit this function.
const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);
if (gop.found_existing) return gop.value_ptr.*;
errdefer assert(o.named_enum_map.remove(enum_type.decl));
- const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(pt);
+ const decl = zcu.declPtr(enum_type.decl);
const target = zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
- try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}),
+ try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{decl.fqn.fmt(ip)}),
toLlvmAddressSpace(.generic, target),
);
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 92cff8b2d0..7a45429da6 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -963,7 +963,7 @@ const DeclGen = struct {
break :cache result_id;
},
.err => |err| {
- const value = try mod.getErrorValue(err.name);
+ const value = try pt.getErrorValue(err.name);
break :cache try self.constInt(ty, value, repr);
},
.error_union => |error_union| {
@@ -3012,12 +3012,11 @@ const DeclGen = struct {
// Append the actual code into the functions section.
try self.spv.addFunction(spv_decl_index, self.func);
- const fqn = try decl.fullyQualifiedName(self.pt);
- try self.spv.debugName(result_id, fqn.toSlice(ip));
+ try self.spv.debugName(result_id, decl.fqn.toSlice(ip));
// Temporarily generate a test kernel declaration if this is a test function.
if (self.pt.zcu.test_functions.contains(self.decl_index)) {
- try self.generateTestEntryPoint(fqn.toSlice(ip), spv_decl_index);
+ try self.generateTestEntryPoint(decl.fqn.toSlice(ip), spv_decl_index);
}
},
.global => {
@@ -3041,8 +3040,7 @@ const DeclGen = struct {
.storage_class = final_storage_class,
});
- const fqn = try decl.fullyQualifiedName(self.pt);
- try self.spv.debugName(result_id, fqn.toSlice(ip));
+ try self.spv.debugName(result_id, decl.fqn.toSlice(ip));
try self.spv.declareDeclDeps(spv_decl_index, &.{});
},
.invocation_global => {
@@ -3086,8 +3084,7 @@ const DeclGen = struct {
try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
try self.spv.addFunction(spv_decl_index, self.func);
- const fqn = try decl.fullyQualifiedName(self.pt);
- try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{fqn.fmt(ip)});
+ try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{decl.fqn.fmt(ip)});
try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
.id_result_type = ptr_ty_id,