authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-01-14 14:53:29+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-15 07:39:05+01:00
log03ed3f56cf0df6864f8a61cfe2108a7f6692bfc6
tree9b4cf66017cce932a1f37a6197b9d5e806c061b3
parent3dddb881bfefbcd64aae7775ed72c42e37503674

Sema: fix `@extern` decls

Closes #18550

3 files changed, 47 insertions(+), 26 deletions(-)

src/Sema.zig+29-24
......@@ -25675,6 +25675,7 @@ fn zirBuiltinExtern(
2567525675 extended: Zir.Inst.Extended.InstData,
2567625676) CompileError!Air.Inst.Ref {
2567725677 const mod = sema.mod;
25678 const ip = &mod.intern_pool;
2567825679 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
2567925680 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
2568025681 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
......@@ -25714,34 +25715,38 @@ fn zirBuiltinExtern(
2571425715 const new_decl = mod.declPtr(new_decl_index);
2571525716 new_decl.name = options.name;
2571625717
25717 {
25718 const new_var = try mod.intern(.{ .variable = .{
25719 .ty = ptr_info.child,
25720 .init = .none,
25721 .decl = sema.owner_decl_index,
25722 .lib_name = options.library_name,
25723 .is_extern = true,
25724 .is_const = ptr_info.flags.is_const,
25725 .is_threadlocal = options.is_thread_local,
25726 .is_weak_linkage = options.linkage == .Weak,
25727 } });
25728
25729 new_decl.src_line = sema.owner_decl.src_line;
25730 // We only access this decl through the decl_ref with the correct type created
25731 // below, so this type doesn't matter
25732 new_decl.ty = Type.fromInterned(ptr_info.child);
25733 new_decl.val = Value.fromInterned(new_var);
25734 new_decl.alignment = .none;
25735 new_decl.@"linksection" = .none;
25736 new_decl.has_tv = true;
25737 new_decl.analysis = .complete;
25738 new_decl.generation = mod.generation;
25739 }
25718 new_decl.src_line = sema.owner_decl.src_line;
25719 new_decl.ty = Type.fromInterned(ptr_info.child);
25720 new_decl.val = Value.fromInterned(
25721 if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn)
25722 try ip.getExternFunc(sema.gpa, .{
25723 .ty = ptr_info.child,
25724 .decl = new_decl_index,
25725 .lib_name = options.library_name,
25726 })
25727 else
25728 try mod.intern(.{ .variable = .{
25729 .ty = ptr_info.child,
25730 .init = .none,
25731 .decl = new_decl_index,
25732 .lib_name = options.library_name,
25733 .is_extern = true,
25734 .is_const = ptr_info.flags.is_const,
25735 .is_threadlocal = options.is_thread_local,
25736 .is_weak_linkage = options.linkage == .Weak,
25737 } }),
25738 );
25739 new_decl.alignment = .none;
25740 new_decl.@"linksection" = .none;
25741 new_decl.has_tv = true;
25742 new_decl.owns_tv = true;
25743 new_decl.analysis = .complete;
25744 new_decl.generation = mod.generation;
2574025745
2574125746 try sema.ensureDeclAnalyzed(new_decl_index);
2574225747
2574325748 return Air.internedToRef((try mod.getCoerced(Value.fromInterned((try mod.intern(.{ .ptr = .{
25744 .ty = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
25749 .ty = switch (ip.indexToKey(ty.toIntern())) {
2574525750 .ptr_type => ty.toIntern(),
2574625751 .opt_type => |child_type| child_type,
2574725752 else => unreachable,
src/codegen/llvm.zig+5-2
......@@ -2941,9 +2941,13 @@ pub const Object = struct {
29412941 const target = owner_mod.resolved_target.result;
29422942 const sret = firstParamSRet(fn_info, zcu);
29432943
2944 const is_extern = decl.isExtern(zcu);
29442945 const function_index = try o.builder.addFunction(
29452946 try o.lowerType(zig_fn_type),
2946 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(zcu))),
2947 try o.builder.string(ip.stringToSlice(if (is_extern)
2948 decl.name
2949 else
2950 try decl.getFullyQualifiedName(zcu))),
29472951 toLlvmAddressSpace(decl.@"addrspace", target),
29482952 );
29492953 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
......@@ -2951,7 +2955,6 @@ pub const Object = struct {
29512955 var attributes: Builder.FunctionAttributes.Wip = .{};
29522956 defer attributes.deinit(&o.builder);
29532957
2954 const is_extern = decl.isExtern(zcu);
29552958 if (!is_extern) {
29562959 function_index.setLinkage(.internal, &o.builder);
29572960 function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
test/behavior/extern.zig+13
......@@ -12,3 +12,16 @@ test "anyopaque extern symbol" {
1212}
1313
1414export var a_mystery_symbol: i32 = 1234;
15
16test "function extern symbol" {
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
20
21 const a = @extern(*const fn () callconv(.C) i32, .{ .name = "a_mystery_function" });
22 try expect(a() == 4567);
23}
24
25export fn a_mystery_function() i32 {
26 return 4567;
27}