Commit 03ed3f56cf
Changed files (3)
test
behavior
src/codegen/llvm.zig
@@ -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);
src/Sema.zig
@@ -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,
test/behavior/extern.zig
@@ -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;
+}