-
Notifications
You must be signed in to change notification settings - Fork 11.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
clang assumes zero-extension of 8-bit arguments in x86, causing interop issues with gcc #43573
Comments
I believe this may be a dupe / related to bug 12207, though it seems like a somewhat serious issue. |
I sent a tentative patch for this in https://reviews.llvm.org/D71178. I think it'd do the right thing, but I still have 10 or so tests to update. |
Ugh.... LLVM has been using the caller-extends-to-32bit ABI for...just about ever. And, except perhaps for this particular bug, GCC also has been generating calls compliant with that. And per https://gcc.gnu.org/PR46942 wanted to depend on it as well -- only didn't due to (at the time) difficulties in codegen. There also appeared to be overall a desire to change the ABI document to state that....but for some reason never happened (with no further followup AFAIK), which is really unfortunate. So, I don't agree this is an LLVM bug, at least not without reopening the discussion on the x86-64 ABI list and coming to some final conclusion on how to update the document to clarify matters. I think:
|
That all seems reasonable, thank you. |
Since ABI document doesn't define the behavior, we can't assume compiler other than clang would sign/zero extend parameter in caller. We should be compatible to other compiler as much as possible. So I think we should remove the sign/zero extend in callee. Removing the assumption (caller has sign/zero extend) in callee would make Clang be compatible with previous clang compiler, gcc and ICC. I didn't see any side effect on doing this. |
And yet, de-facto, other compilers DO sign/zero extend in caller, and therefore DO interop with Clang. It seems silly to require extension on both sides of the call (though, of course, GCC has been doing that). |
However ICC doesn't sign/zero extend in caller. See https://gcc.godbolt.org/z/8aaPP33cG. So if the caller is built by ICC and callee is built by Clang, the issue happen. We can't assume all compiler do sign/zero extend in caller. |
Ah, yes; that's an unfortunate new piece of information here. :( |
Also, GCC doesn't guarantee the sign extension. It usually does, due to integer promotion rules, but it might not if you're passing e.g. an |
Since it's not clear on the bug trail (discussions happened elsewhere) -- The consensus from discussions on the ABI list and elsewhere is that Clang is indeed incorrect per the x86 psABI specification. I think that's unfortunate (and it also would've been nice if the spec had been more clearly written from the get-go) but being that as it may: the consensus is that x86 psABI specifies that no zero/sign-extension is required for callers passing 8/16-bit values, so this is a Clang bug that needs to be fixed. The only issue for Clang is that it should fix this without breaking compatibility with old versions of itself. Thus, it must stop assuming values have been extended in the callee, but continue to (possibly-redundantly) extend in the caller. |
Extended Description
When receiving 8-bit-wide arguments in extern function, clang seems to assume the argument has been zero-extended by the caller.
According to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92821#c2:
https://godbolt.org/z/BNHxEY has a comparison of clang and gcc output for the attached test-case. GCC correctly does an 8-bit load, disregarding the rest of the bits in the register.
This causes real problems when gcc-built functions call into llvm-built functions. See https://bugzilla.mozilla.org/show_bug.cgi?id=1600735 for an example that happens on Firefox. GCC may not always sign-extend in the caller.
In the Firefox case the LLVM-built function is Rust code, but per the above godbolt link it also seems to reproduce with C / C++.
The text was updated successfully, but these errors were encountered: