Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Document rustc bugs #3

Open
Jasper-Bekkers opened this issue Sep 30, 2021 · 1 comment
Open

Document rustc bugs #3

Jasper-Bekkers opened this issue Sep 30, 2021 · 1 comment

Comments

@Jasper-Bekkers
Copy link

The code has a comment along the lines of "There are known rustc bugs that will prevent it from working", it would be nice if the known issues were linked in the README or documentation.

@thomcc
Copy link
Owner

thomcc commented Sep 30, 2021

It's mostly around #[used] statics getting removed. I think rust-lang/rust#47384 is the big one but the changes mentioned in the last couple comments here rust-lang/rust#40289 (comment) might become a problem soon too on some targets (or maybe I'm misunderstanding).

There's also short list of issues where a #[used] just gets dropped because we're doing an incremental build and, well, you got unlucky. Tough cookies. I don't know if there's a a specific issue for that, and it's pretty rare, but when I've had it happen it usually is very hard to work around.

Anyway, it's generally enough to ensure that some of the code in the module is reachable. This should keep the module from getting thrown out, which IME seems to be what usually causes the #[used] to get thrown out. Note tho that "reachable" can be fuzzy and non-obvious (even ignoring inlining and such, bugs like rust-lang/rust#50007 complicate things).

If you can compile with LTO its pretty reliable IME, since it becomes one big module. Also, if you can control arbitrary build flags in your use case, it can be even more robust by directly asking the linker not to remove certain things. Also, note that some targets are a lot worse about this than others, unfortunately.


Unfortunately, to implement __attribute__((constructor))/C++ static ctors and such in a fully robust way, clang/LLVM uses a special variable (@llvm.global_ctors) which has a special linkage mode (appending linkage). This has a lot of special casing in LLVM itself, and is more than just outputting to a specific link section (which is what I'm doing in startup.

Sadly, there's not really a way for us to access something like this from Rust. We'd need rustc to do it for us, e.g. it'd need to be supported by the Rust language which... seems very unlikely to happen (it can't really be supported on some of Rust's targets, like wasm, bare metal, ...).

Just putting the functions in the right section works well in practice, but isn't perfect... (Although, it'd work way better in practice if #[used] did actually what it promised 😡).


All that said, in practice most of the time I use startup I don't have any problems, so it's highly a YMMV situation. I'd recommend it less for library code and more for application code, since you can control a lot more there.

There are also a few patterns you should avoid if possible: I wouldn't recommend it in situations where you have a big block of code in a module, that has no public items, but uses startup! to add some functionality defined in that module in some registry. This kind of thing tends to be where a lot of issues happen.

That said, this kind of thing is very useful for some designs. :(

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants