Hello
I have this snippet:
const SomeType = extern struct { value: u64 };
fn MakeSymbols(comptime name1: []const u8, comptime name2: []const u8) void {
const A = SomeType{ .value = 10 };
@export(A, .{
.name = name1,
});
const B = &A;
@export(B, .{
.name = name2,
});
}
pub fn main() void {
comptime MakeSymbols("A", "B");
}
On an ARM Macbook, this generates the following two symbols:
.section __TEXT,__const
.globl _A
.p2align 3, 0x0
_A:
.quad 10
.section __DATA,__const
.globl _B
.p2align 3, 0x0
_B:
.quad _A
Notice that _B
references _A
, which is good.
Then I tweak the example to specify the section for A
:
const SomeType = extern struct { value: u64 };
fn MakeSymbols(comptime name1: []const u8, comptime name2: []const u8) void {
const A = SomeType{ .value = 10 };
@export(A, .{
.name = name1,
.section = "__TEXT,__myconst", // this is new
});
const B = &A;
@export(B, .{
.name = name2,
});
}
pub fn main() void {
comptime MakeSymbols("A", "B");
}
This modified snippet gives me the following symbols:
.section __TEXT,__const
.p2align 3, 0x0
_symbols.MakeSymbols__anon_2728:
.quad 10
.section __TEXT,__myconst
.globl _A
.p2align 3, 0x0
_A:
.quad 10
.section __DATA,__const
.globl _B
.p2align 3, 0x0
_B:
.quad _symbols.MakeSymbols__anon_2728
Notice that _B
no longer references _A
but instead points to _symbols.MakeSymbols__anon_2728
, which is a non-global duplicate of symbol _A
. This behavior occurs regardless of which section I specify for A
(even if I specify its default section __TEXT,__const
!)
Of course, I can rewrite this example to use the (more concise) export
and linksection
keywords:
const SomeType = extern struct { value: u64 };
export const A linksection("__TEXT,__myconst") = SomeType{ .value = 10 };
export const B = &A;
pub fn main() void {}
And this does work! In particular, it puts _A
in the specified section and _B
still references _A
:
.section __TEXT,__myconst
.globl _A
.p2align 3, 0x0
_A:
.quad 10
.section __DATA,__const
.globl _B
.p2align 3, 0x0
_B:
.quad _A
However, I cannot use the export
keyword inside of a comptime function – which is the crux of what I am going for. My use case is generating symbols for the Objective-C runtime at comptime (akin to what clang/LLVM/ld do for actual Objective-C code). In particular, I’d like to do so using a comptime function so that I can encapsulate the logic required generate the different ObjC symbols that the runtime consumes.
Not sure if pretending to be Objective-C is a valid Zig use case – though it is tantalizing to have potentially zero-overhead interop with Apple’s frameworks from Zig. Even so, I would like to better understand the semantic difference between
@export
and export
+ linksection
that lead to this difference in the generated assembly.
Zig version: 0.11.0-dev.3892+0a6cd257b