diff options
| author | Matthew Lugg <mlugg@mlugg.co.uk> | 2024-07-11 23:27:13 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-11 23:27:13 +0100 |
| commit | 80d7e260d78400b841f15e3350473650b87931a5 (patch) | |
| tree | 3035bae743da24cbe1d5046469fea0a5542a8829 /src/codegen | |
| parent | 45be80364659332807b527670514332a4b835f84 (diff) | |
| parent | 77810f288216ef3e35f3d0df4a04351297560a5e (diff) | |
| download | zig-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.zig | 35 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 72 | ||||
| -rw-r--r-- | src/codegen/spirv.zig | 13 |
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, |
