-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: different way to specify exported symbols #462
Comments
When I made the comments last night I had not put together all the parts. It seems like there are a few mostly-orthogonal things here:
The reason I say mostly-orthogonal is, as you point out, that you need to have both a "global" visibility on a function and have it use the C calling convention in order for C code to call it. So the new export syntax above is only for things visible to C? As I understand it (and maybe I am missing something important due to my lack of experience with Zig!), a C-callable function differs in two ways from a standard Zig function. It must be visible at the global level and it must use the C calling convention. So you would still use "pub" for module-level entities, right? Would there be a use case for global entities that are not C-callable? If so, maybe then "export" becomes "global" and you retain the ccc part?? (I moved the original incoherent ideas over to the forum where they belong.) |
I have related proposal. Modules (or packages) provide several features:
Here's the proposal about encapsulation:
This way one could:
|
This proposal also makes things like this more clear: export nakedcc fn __chkstk() {
@setDebugSafety(this, false);
if (comptime builtin.os == builtin.Os.windows) {
if (comptime builtin.arch == builtin.Arch.x86_64) {
asm volatile (
\\ push %%rcx
\\ cmp $0x1000,%%rax
\\ lea 16(%%rsp),%%rcx // rsp before calling this routine -> rcx
\\ jb 1f
\\ 2:
\\ sub $0x1000,%%rcx
\\ test %%rcx,(%%rcx)
\\ sub $0x1000,%%rax
\\ cmp $0x1000,%%rax
\\ ja 2b
\\ 1:
\\ sub %%rax,%%rcx
\\ test %%rcx,(%%rcx)
\\
\\ lea 8(%%rsp),%%rax // load pointer to the return address into rax
\\ mov %%rcx,%%rsp // install the new top of stack pointer into rsp
\\ mov -8(%%rax),%%rcx // restore rcx
\\ push (%%rax) // push return address onto the stack
\\ sub %%rsp,%%rax // restore the original value in rax
\\ ret
);
unreachable;
}
}
@setGlobalLinkage(__chkstk, builtin.GlobalLinkage.Internal);
} Now it's: comptime {
if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.x86_64) {
export __chkstk = windows_check_stack;
}
}
nakedcc fn windows_check_stack() {
@setDebugSafety(this, false);
asm volatile (
\\ push %%rcx
\\ cmp $0x1000,%%rax
\\ lea 16(%%rsp),%%rcx // rsp before calling this routine -> rcx
\\ jb 1f
\\ 2:
\\ sub $0x1000,%%rcx
\\ test %%rcx,(%%rcx)
\\ sub $0x1000,%%rax
\\ cmp $0x1000,%%rax
\\ ja 2b
\\ 1:
\\ sub %%rax,%%rcx
\\ test %%rcx,(%%rcx)
\\
\\ lea 8(%%rsp),%%rax // load pointer to the return address into rax
\\ mov %%rcx,%%rsp // install the new top of stack pointer into rsp
\\ mov -8(%%rax),%%rcx // restore rcx
\\ push (%%rax) // push return address onto the stack
\\ sub %%rsp,%%rax // restore the original value in rax
\\ ret
);
unreachable;
} And now that symbol export fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 {
if (!want_main_symbol) {
@setGlobalLinkage(main, builtin.GlobalLinkage.Internal);
unreachable;
}
callMain(usize(c_argc), c_argv, c_envp) %% return 1;
return 0;
} becomes comptime {
if (want_main_symbol) {
export main = c_main_entry_point;
}
}
ccc fn c_main_entry_point(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 {
callMain(usize(c_argc), c_argv, c_envp) %% return 1;
return 0;
} and now exporting the main symbol is allowed for the user. |
Problem: We have some messy complications regarding the difference between pub and export.
pub
,export
, and unqualified are the 3 visibility modifiers. Pub makes sense. But if it'sexport
then it goes into the global namespace as well as being exposed in the current module.export
automatically changes the calling convention of a function to C calling convention, which is represented in type syntax asextern fn()
extern fn();
also changes calling convention to CCC.nakedcc
,stdcallcc
,coldcc
. But noccc
.export
ed functions have special requirements such as disallowing comptime parameters and use of certain types.@import
a module which exported a function, that function name is meant for the global namespace, but you're going to call it through a module namespace.extern fn() { ... }
for a function definition that wants the C calling convention but does not need to be exported.export const Foo = extern struct { ... }
.Here's the proposal:
export
from functions and global variables. (and generally remove it as a visibility modifier)ccc
as a calling convention. Useccc fn()
instead ofextern fn()
for the type syntax.I think this solves all the problems.
The text was updated successfully, but these errors were encountered: