-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add a freestanding target #106
Conversation
cc @Tobba @thestinger @alexcrichton @vhbit @bharrisau This supercedes PR #7. |
This looks like good work! I'm very excited to see more bare-metal Rust users! |
The issue with libc/m/etc. could be avoided if we had the option to output an object file. Thoughts? |
We already do ( |
I want a single line calling rustc in my build script, that makes my kernel (possibly involving linker scripts etc). |
We have managed to "get something working" for zinc.rs, but there are a few hacks needed at the moment to support building with a single rustc call (creating empty libmorestack, for example). That being said, stack safety is a nice thing to have (on the supported platforms), and LLVM supports thumbv[67]m for this. In the future it would be great to have a syntax extension for a custom prelude/epilogue for stack safety, but until then is it better to experiment with Rust on bare-metal without stack safety? I think so; stack safety is important for production, but if we can ignore that one issue for the moment it gives us the ability to find any other issues with rust on bare-metal. That being said, zinc.rs uses stack safety for the task model. So we may end up continuing to use the |
On any platform with an MMU, the segmented stack feature is a poor way of providing stack safety. It's only used as a temporary hack before a portable equivalent to |
(And on ARM even when you don't have MMU, you have an MPU you can use) On Tue, Jun 3, 2014 at 10:01 PM, Daniel Micay notifications@github.com
|
Yeah, it might be a decision to only support stack safety on devices that include the optional MPU. |
compile time and runtime, reducing unnecessary surprises for the freestanding | ||
author and allowing the use of only rustc to compile the crate, rather than | ||
manually assembling and linking LLVM bitcode. Providing linker arguments | ||
manually is probably unavoidable in these cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I entirely understand this section. The compiler forcibly links to only two libraries, libmorestack and libcompiler-rt. The morestack library is used to provide the __morestack
function required by LLVM's implementation of segmented stacks. This library would be omitted if the compiler is not compiling the current crate with segmented stacks disabled.
The other library, compiler-rt, is also required by LLVM. This library is not a dependency per-se in that I am unaware of any libc functions it depends on. No matter what your target is, I am under the impression that you want to link compiler-rt. This includes any "freestading platform" it sounds like you're describing here.
You mention libc and libm, but the compiler knows nothing about these libraries. They are linked to when you manually link to the liblibc
crate, but never implicitly by the compiler.
Also, when you say "providing linker arguments manually is probably unavoidable", what are you referring to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, don't know where I thought libc/libm came from. As for compiler-rt, if you need it, you can build it for your platform -- or just avoid the features that require it. As to linker arguments, I'm thinking things like linker scripts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have been compiling zinc.rs without compiler-rt, I'm not exactly sure of what it supports. From memory, many of the #ifdef
directives were about linux (i.e. it doesn't build properly for some targets).
Example of linker arguments would be linker scripts -T
and map file -Map
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that LLVM will lower intrinsics and other functionality in your program into calls to functions in libcompiler-rt. From this, it is my understanding that if you do not link compiler-rt you will eventually run into linker errors.
With this understanding, why do you not want to link to compiler-rt? Is it difficult to build?
@bharrisau I still have plans for allowing stack safety, through static analysis (I need to write up another blog post on this subject), but it does forgo most uses of dynamic dispatch (and require annotating maximum stack size usage for them). |
@alexcrichton I've reworded some of the misguided bits. |
and runtime, reducing unnecessary surprises for the freestanding author and | ||
allowing the use of only rustc to compile the crate, rather than manually | ||
assembling and linking LLVM bitcode. Providing linker arguments manually is | ||
probably unavoidable in these cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My previous discussion has now been folded away by github, so I'll reiterate my point here original link.
I don't understand the use case for not wanting to link to compiler-rt. Is there a concrete reason for why this is undesirable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yet another thing you need to download and build, for features you're probably not using (floats, 64-bit math on 32-bit targets, emulating atomics with locks, fixed point arith, ...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to talk concretely here. The compiler-rt library is tiny and very easy to build. It has one function per object, so the linker strips out everything you don't use.
Without a conrete reason as to why, I don't see why the compiler should stop linking to compiler-rt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree there are instances where you probably do want compiler-rt, but that those would be outweighed by the cases where you don't. (Some fun reading, though only slightly topical: http://yarchive.net/comp/linux/libgcc.html)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The concrete reason being it's just another dependency you need. I'm not going to argue that it's large or a runtime burden (because that would just be false). Should we instead add build system support for building and distributing it for *-unknown-unknown
? I wouldn't be against that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My experience with compiler-rt was a complete nightmare. So if it is possible to go without it - it's better to go without it.
Avoiding compiler-rt means providing all of the support functions expected by LLVM's code generation on your own. You can almost get away with using libgcc_s
, but it's missing functions required by Rust's code generation.
- While working on proper backport I've "worked" with one of code owners. Worked in this case means I've pinged him every 2-3 days for about a month until full despair.
That's pretty much how the LLVM project works right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't run into any of these support functions being missing on arm-none-eabi (thumb2).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't run into any of these support functions being missing on arm-none-eabi (thumb2).
The features provided by compiler-rt are well known and we don't need to rely on anecdotes to know that significant portions of the language are missing without it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't run into any of these support functions being missing on arm-none-eabi (thumb2).
What do you mean by "being missing"? I do link to libgcc.a for some of those on thumbv7m, as I don't use compiler-rt. They are definitely required in lots of cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apologies - the build system is linking against libgcc.a, so I must be getting them from there.
@alexcrichton I feel like a good target for freestanding is "only requires a stack". I feel like with that baseline, everything else can be built up? |
I don't feel very strongly about any of this except that we really ought to have a target where we do the minimum possible work to get Rust up and going, without having to stub out anything. |
I do agree that seems like a good target. I believe that the components needed to meet that target include libcore and libcompiler-rt, but I would believe that split-stacks are not part of that target. In general, it seems to me that we would want to consider whitelisting platforms for segmented-stack support and just turn it off on all other platforms (but that's it for now). |
Yeah, a whitelist probably makes more sense, but I feel like having to opt-into stack unsafety is a better idea :( |
Excellent, this took long enough Whitelist or blacklist is probably the way to go about the segmented stack problem, I think the issues with libc can be sorted out with some additional cfg's to not try to link those on an unknown OS |
I actually like the Given that we run on platforms without even an MPU, I would like to have at least some stack safety between threads, which the prologue does. I'm kind of ok with how it works with I'm not ok with reserving 256 bytes after the stack (on arm), that one should at least be configurable. There's one more thing with running on metal and crates (that's a bit out of the scope of this RFC though) — you cannot reliably export the symbols from within the crate. libzinc currently provides a few ISRs, it's compiled to rlib and later linked into libapp, which is end user code (also an rlib). libapp geets linked into final wrapper, which is app.rs (staticlib emitted as obj) which re-exports a few required symbols from libzinc. That obj file is further linked with another rlib emitted as obj, that provides other globally visible symbols. I'm not sure how to actually fix that (other than make some "super-export" that ignores other visibility rules and forcefully publishes the "C" symbol). |
@farcaller I believe I can do better than |
@farcaller: You should use a re-export if you want it re-exported. There's no need for additional feature, but perhaps there are bugs to be fixed.
It's fine on platforms without an MMU, but it's needless overhead on most. |
@cmr: with os unknown what is an executable? Do you mean a static ELF object with the executable bits in? |
@thestinger: That doesnt actually work. Currently this needs delicately unpacking the bitcode, unfucking it to remove split stacks and then doing a maze of linking, which probably includes several pages of hacks |
@taralx yeah. |
We could allow disabling split stacks on a per-crate basis. Then calling | ||
functions from that crate is then unsafe, and we would need to compensate for | ||
this somehow. We would still need to add a way to not link to | ||
libc/libm/copmiler-rt. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling.
TL;DL - Add UnknownOs, disable dylibs, disable segmented-stack, do not include any default link time libraries. Developer is responsible for unsafe stacks, defining LLVM intrinsics, and lots of linker arguments. I'm in favour of this, but it shouldn't be the end solution. We need a portable solution for stack safety on systems without MPU or MMU. |
I'd like this a lot. Also it would be nice if rlibs for cross-compiling were build nightly too. |
Given that rust-lang/rust#14715 landed today which includes disabling split-stack for iOS target, I think it would be quite trivial to push freestanding forward. I can actually go and provide a test implementation for that if of any use. |
I had something done up in rust-lang/rust#12841. |
I'm closing this in favor of #131 |
No description provided.