-
Notifications
You must be signed in to change notification settings - Fork 12
Change main from extern "C" to extern "Rust" #34
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
Conversation
Cool, I didn't know you could do that. A concern I have is that this change would break mustang, because in mustang, origin calls an Maybe the way to fix this is though to make mustang handle this. If we renamed origin's Also, if we're using Ooh, and this may also be an opportunity to replace |
I am not sure that is the best solution. I feel like origin should strive to be independent of mustang, that is already my use case and I feel like the better solution is the other way around and let mustang handle the change. If you could point me to where mustang relies on this I could form a better opinion but I feel like mustang should instead wrap in an extern "C" the extern "Rust" if we want to mantain compatibility
That feels like the next logical step, after all we are abandoning libc here and are in pure rust territory, we should be free to make a safer api that better reflects the rust way of doing things. Coming back to the topic of whether or not to rename main to origin_main I actually came up with what I think is an even better and more idiomatic solution. Should origin even handle main as an extern? I feel like a better solution would be to actually make origin more composable and allow to insert any function pointer as main. Ideally this could allow for the main function to be named anything and ultimately have a proc_macro like |
Following on my previous comment, ideally origin would not handle main in the library directly but instead users of the library would be able to write code like the following: #[panic_handler]
fn panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort()
}
#[origin::main]
fn main(args: &'static [u8]) -> i32 {
0
} Which would roughly expand to something like this: #[panic_handler]
fn panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort()
}
fn main(args: &'static [u8]) -> i32 {
0
}
#[naked]
#[no_mangle]
unsafe extern "C" fn _start() -> ! {
use core::arch::asm;
fn entry(mem: *mut usize) -> ! {
origin::_some_function_that_inits_the_runtime();
let args = origin::_some_function_that_computes_args();
let status = main(args);
origin::exit(status)
}
#[cfg(target_arch = "x86_64")]
asm!(
"mov rdi, rsp", // Pass the incoming `rsp` as the arg to `entry`.
"push rbp", // Set the return address to zero.
"jmp {entry}", // Jump to `entry`.
entry = sym entry,
options(noreturn),
);
} This would allow normal programs to not need to look into origin internals and for more specif use cases like mustang, they can call the provided functions and manually handle the program initialization |
Actually turns out we don't need to an extern "C" to jump to a function, so I update the code to reflect that. The only function that ever needs to use the C abi is |
My instinct here is that handling One option would be to go the other way, and make origin's Consequently, I expect the most common way to use this API will be via wrappers, whether that's |
I can confirm that Mustang can do what it needs with a wrapper here. So that's fine. |
I think we might want to not pass args at all to the main function. I don't think there is any way to pass them in a "rusty" way without involving some complex logic and/or externa crates. After all isn't this what normal rust programs expect anyway? Imo the best way to handle args is the way std does by providing an iterator api, which in this case could be handled by origin-stdio instead of origin itself
If we truly wanna make origin more flexible then it shouldn't handle main at all, instead it should just export the appropriate function to let other crates like mustang and origin-stdio handle the initialization. I still think there is value in allowing for origin-only programs and a proc_macro would fulfill that role, it would live in a separate crate called origin-macros which would be an optional dependency disabled by default. By the way, sorry if this comment is somewhat strange but github is experiencing some kind of outage and I've spent the better part of an hour trying to write this comment. |
Currently origin requires users of the library to supply a main function with the following definition
However it is not necessary to use an
extern C
there since this never crosses any ffi boundary and is always compiled from source. This pr changes this from anextern C
to anextern Rust
. This allows to omit any extern declarations when writing main since the Rust extern is always implied.Main function before this change:
Main function after this change
I had opened #33 at first without realizing I was working with a very outdated branch so this supersedes that