Skip to content
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

Compiling libcore without SSE leads to LLVM ERROR: SSE register return with SSE disabled #26449

Closed
gz opened this issue Jun 20, 2015 · 19 comments
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug.

Comments

@gz
Copy link
Contributor

gz commented Jun 20, 2015

May be related to: #26025
At least compilation seems to work for June 17th nightly and earlier.

I tried this (creating libcore library without the use of vector instructions; this is typically done in case one wants to use libcore in kernel level code):

rustc-nightly/src/libcore $ rustc --crate-type=lib --emit=link -O -C soft-float -C target-feature=-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2 -g --emit=obj -C soft-float -C no-vectorize-slp -C no-vectorize-loops --crate-name core lib.rs 
LLVM ERROR: SSE register return with SSE disabled

I expected to see this happen: Successful compilation.

Instead, this happened: LLVM ERROR: SSE register return with SSE disabled

Meta

rustc --version --verbose:
rustc 1.2.0-nightly (2f56839 2015-06-18)
binary: rustc
commit-hash: 2f56839
commit-date: 2015-06-18
host: x86_64-unknown-linux-gnu
release: 1.2.0-nightly

@steveklabnik steveklabnik added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jun 23, 2015
@Roxxik
Copy link

Roxxik commented Jun 29, 2015

I've investigated this a little further:
libcore cannot be compiled without mmx, sse and sse2
the following commands all fail

$ rustc -O -g --crate-type=lib --emit=link --emit=obj -C target-feature=-mmx --crate-name core lib.rs
LLVM ERROR: SSE register return with SSE disabled
$ rustc -O -g --crate-type=lib --emit=link --emit=obj -C target-feature=-sse --crate-name core lib.rs
LLVM ERROR: SSE register return with SSE disabled
$ rustc -O -g --crate-type=lib --emit=link --emit=obj -C target-feature=-sse2 --crate-name core lib.rs
LLVM ERROR: SSE2 register return with SSE2 disabled

the command above without those three disabled works for me

$ rustc --crate-type=lib --emit=link -O -C soft-float -C target-feature=-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2 -g --emit=obj -C soft-float -C no-vectorize-slp -C no-vectorize-loops --crate-name core lib.rs

I haven't tested whether the resulting object file is functional.

$ rustc --version --verbose

rustc 1.3.0-dev (40db46c 2015-06-29)
binary: rustc
commit-hash: 40db46c
commit-date: 2015-06-29
host: x86_64-unknown-linux-gnu
release: 1.3.0-dev

@eternaleye
Copy link
Contributor

To explain somewhat:

The x86_64 ABI states that it is mandatory for floating-point return values to be passed in SSE registers. On one level, this makes an enormous amount of sense: the 387 FPU being a weird 80-bit thing causes real issues, and every x86_64 CPU possesses SSE2.

On the other hand, LLVM doesn't offer any functionality along the lines of GCC's -mfpmath to override this behavior. At least at one point, adding +soft-float to the target fixed the issue, but I've heard that no longer does the trick.

@thepowersgang
Copy link
Contributor

And to state why one would want to disable SSE etc. When writing kernel-mode code, it is very undesirable to touch the floating-point or vector units, as they both require explicit initialization, and have very large register states that would have to be saved on all context switches.

@eternaleye
Copy link
Contributor

Personally, I'd actually like the idea of splitting libcore into float-free and float-using parts, as there are embedded CPUs with no FPU that are also of interest.

@gz
Copy link
Contributor Author

gz commented Jul 2, 2015

Just adding a feature to disable floating point related functions/types etc. should be sufficient for architectures that do not support it or codebases that do not want to use it, right?

@thepowersgang
Copy link
Contributor

@gz Adding a cfg() flag that disables compilation of the floating-point functions did allow libcore to be compiled with SSE etc disabled. See https://github.com/thepowersgang/rust_os/blob/master/libcore_nofp.patch for a patch on for the latest nightly.

I'm not sure what the best long-run solution would be, but probably having a #[cfg] flag is best (and making sure it gets tested correctly).

As a related note - Could that LLVM error message be changed to include the offending function? (I'm not sure where such a change would happen, in the rust branch, or in upstream LLVM)

gz pushed a commit to gz/rust that referenced this issue Jul 3, 2015
This allows to compile libcore on architectures that lack floating point support
or to use libcore in kernel code without worrying about saving and restoring
the floating point register state inside the kernel.
gz added a commit to gz/rust that referenced this issue Jul 3, 2015
@gz
Copy link
Contributor Author

gz commented Jul 4, 2015

FYI I submitted a pull request for this: #26749

@gz
Copy link
Contributor Author

gz commented Aug 8, 2015

@Zoxc
Copy link
Contributor

Zoxc commented Oct 30, 2015

If you build libcore with floating point support and link to it using -C lto you will only get LLVM errors if you actually use some floating point functionality in libcore. That is how I use it in my kernel.

@gz I don't think building libcore without floating point has ever worked. Do you happen to know a version where this works?

@emk
Copy link
Contributor

emk commented Oct 30, 2015

I'm also getting bitten by this one, for much the same reasons that the powersgang mentions above. I'm starting from Philipp Oppermann's series of blog posts on writing an OS in Rust, and trying to add interrupt support. Unfortunately, saving the floating point registers on every interrupt slows everything down and requires much more fiddling around, which is why most x86 kernels avoid floating point. And of course, there are plenty of other processors without floating point out there.

For this kind of bare-metal use, it would be very nice to have some way of convincing Rust to stop emitting floating point instructions and still manage to build core.

@thepowersgang
Copy link
Contributor

At the moment - the best way is to patch libcore locally before compiling, I'm still maintaining the patchset that does that for my kernel project.

@emk
Copy link
Contributor

emk commented Oct 30, 2015

@thepowersgang: Thank you for the suggestion! For anybody else running into this problem, I found a copy of disable_float libcore_nofp patch in @thepowersgang's OS repository. It's surprisingly small.

Looking at your patch, it looks very straightforward and "principled", if you will: It specifically excludes everything in libcore related to floating point without any gross hackery. It just disables f32, f64, and the related APIs.

@gz
Copy link
Contributor Author

gz commented Oct 31, 2015

@Zoxc: Yes, it worked before #26025 (see bug description)

@parched
Copy link
Contributor

parched commented Jul 21, 2016

@gz You need to add the +soft-float target feature

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 22, 2017
@steveklabnik
Copy link
Member

Triage: it's been pretty much four years since a significant problem was posted in this thread, and as @parched said three years ago, by putting

"features": "-mmx,-sse,+soft-float",

in your target json file, and this should be working. For example, @thepowersgang hasn't been using their patch since 2016, and does this instead: thepowersgang/rust-barebones-kernel@78beb04

As such, I'm going to close this bug. If someone is still running into this, please let me know!

@pnkfelix
Copy link
Member

@steveklabnik it looks like someone ran into an LLVM Assert that appears strongly related to this, in #65844

@steveklabnik
Copy link
Member

Interesting. Do you think that warrants re-opening this ticket as well?

@pnkfelix
Copy link
Member

I dunno. I guess if still no one is actually trying to compile libcore with sse disabled, then this might as well remain closed

@SK83RJOSH
Copy link

SK83RJOSH commented Aug 5, 2023

I know this is a very old issue, and I normally wouldn't bump it, but I ran into this while naively disabling sse to do some benchmarks today. Not a huge issue, except that when using --target=x86_64-pc-windows-msvc, LLVM happily generates an executable with bad codegen. Took me a few hours to realize that std::f32::min/max are returning non-zeroed/uninitialized stack memory due to presumably this exact issue with libcore.

Not sure if anyone cares since it seems to have gone unnoticed this long, but it's a pretty big footgun that can go unnoticed for quite some time.

Super simple repro (using cargo test on Windows with rustflags = ["-Ctarget-feature=-sse"] in config.toml):

#[test]
pub fn main() {
    assert_eq!(3_f32, 3_f32.min(4_f32));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests