srctree

Jacob Young parent 3dddb881 03ed3f56
Sema: fix `@extern` decls

Closes #18550

inlinesplit
src/Sema.zig added: 50, removed: 29, total 21
@@ -25675,6 +25675,7 @@ fn zirBuiltinExtern(
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const mod = sema.mod;
const ip = &mod.intern_pool;
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
@@ -25714,34 +25715,38 @@ fn zirBuiltinExtern(
const new_decl = mod.declPtr(new_decl_index);
new_decl.name = options.name;
 
{
const new_var = try mod.intern(.{ .variable = .{
.ty = ptr_info.child,
.init = .none,
.decl = sema.owner_decl_index,
.lib_name = options.library_name,
.is_extern = true,
.is_const = ptr_info.flags.is_const,
.is_threadlocal = options.is_thread_local,
.is_weak_linkage = options.linkage == .Weak,
} });
 
new_decl.src_line = sema.owner_decl.src_line;
// We only access this decl through the decl_ref with the correct type created
// below, so this type doesn't matter
new_decl.ty = Type.fromInterned(ptr_info.child);
new_decl.val = Value.fromInterned(new_var);
new_decl.alignment = .none;
new_decl.@"linksection" = .none;
new_decl.has_tv = true;
new_decl.analysis = .complete;
new_decl.generation = mod.generation;
}
new_decl.src_line = sema.owner_decl.src_line;
new_decl.ty = Type.fromInterned(ptr_info.child);
new_decl.val = Value.fromInterned(
if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn)
try ip.getExternFunc(sema.gpa, .{
.ty = ptr_info.child,
.decl = new_decl_index,
.lib_name = options.library_name,
})
else
try mod.intern(.{ .variable = .{
.ty = ptr_info.child,
.init = .none,
.decl = new_decl_index,
.lib_name = options.library_name,
.is_extern = true,
.is_const = ptr_info.flags.is_const,
.is_threadlocal = options.is_thread_local,
.is_weak_linkage = options.linkage == .Weak,
} }),
);
new_decl.alignment = .none;
new_decl.@"linksection" = .none;
new_decl.has_tv = true;
new_decl.owns_tv = true;
new_decl.analysis = .complete;
new_decl.generation = mod.generation;
 
try sema.ensureDeclAnalyzed(new_decl_index);
 
return Air.internedToRef((try mod.getCoerced(Value.fromInterned((try mod.intern(.{ .ptr = .{
.ty = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
.ty = switch (ip.indexToKey(ty.toIntern())) {
.ptr_type => ty.toIntern(),
.opt_type => |child_type| child_type,
else => unreachable,
 
src/codegen/llvm.zig added: 50, removed: 29, total 21
@@ -2941,9 +2941,13 @@ pub const Object = struct {
const target = owner_mod.resolved_target.result;
const sret = firstParamSRet(fn_info, zcu);
 
const is_extern = decl.isExtern(zcu);
const function_index = try o.builder.addFunction(
try o.lowerType(zig_fn_type),
try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(zcu))),
try o.builder.string(ip.stringToSlice(if (is_extern)
decl.name
else
try decl.getFullyQualifiedName(zcu))),
toLlvmAddressSpace(decl.@"addrspace", target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@@ -2951,7 +2955,6 @@ pub const Object = struct {
var attributes: Builder.FunctionAttributes.Wip = .{};
defer attributes.deinit(&o.builder);
 
const is_extern = decl.isExtern(zcu);
if (!is_extern) {
function_index.setLinkage(.internal, &o.builder);
function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
 
test/behavior/extern.zig added: 50, removed: 29, total 21
@@ -12,3 +12,16 @@ test "anyopaque extern symbol" {
}
 
export var a_mystery_symbol: i32 = 1234;
 
test "function extern symbol" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
 
const a = @extern(*const fn () callconv(.C) i32, .{ .name = "a_mystery_function" });
try expect(a() == 4567);
}
 
export fn a_mystery_function() i32 {
return 4567;
}