-
-
Notifications
You must be signed in to change notification settings - Fork 262
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
Various tweaks for Android, plus an Alpine fix #2917
Conversation
dmd/compiler.d
Outdated
@@ -107,7 +107,7 @@ else | |||
} | |||
Identifier id = Id.entrypoint; | |||
auto m = new Module("__entrypoint.d", id, 0, 0); | |||
scope p = new Parser!ASTCodegen(m, cmaincode, false); | |||
auto p = new Parser!ASTCodegen(m, cmaincode, false); |
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 reason for all these changes from stack-allocating the parser to GC allocation is that the "bump-the-pointer" dmdfe GC aligns to 128-bit by default, whereas stack allocation aligns to 64-bit.
The problem is that when CTFloat.parse
is called in Lexer.inreal
, it segfaults when trying to assign to t.floatvalue
, because it expects that union in the token to be 128-bit aligned and uses a MOVAPS
instruction. If the parser is 128-bit aligned, then so is the token and the union and everything works. I tried putting an align(16)
on the Parser
or Lexer
, but it makes no difference. Maybe getting scope
to use those alignments is the real fix.
I checked why this doesn't hit on linux/x64, where the stack-allocated parser isn't 128-bit aligned either, and it's because LLVM generates a FSTPT
when setting t.floatvalue
there, which doesn't care about alignment.
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.
So the C++ code assumes a 16-bytes alignment for 128-bit long double
, which seems to make perfect sense. Judging by your comment and a superficial quick glance, the issue seems to be that the Token
(or its nested union's) alignment on the D side doesn't match (as the Tokens seem to be allocated in D IIRC). And I would guess that that's due to the used host compiler's real.alignof
not returning 16, which should be trivial to check. You can also just extract the Token
declaration and check its alignment (and the union's offset) with the host compiler.
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 played around with run.dlang.io, and it looks as if Token
is 16-bytes aligned, and the union's offset 64 bytes: https://run.dlang.io/is/WnzZVI
If so, then these Tokens must be somehow wrongly allocated (in IR, we obviously use align 16
for locals on the stack).
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.
After some more tests, I think it's scope
; the Parser
instance allocated on the stack only has an 8-bytes alignment (corresponding to the class reference alignment).
Edit: Ah yeah,
whereas stack allocation aligns to 64-bit [...] Maybe getting scope to use those alignments is the real fix.
that's exactly it, I should have read carefully.
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 misalignment of scope
class objects is a pretty big bug imo! Nice find.
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.
[related: #1692]
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.
OK, given the long-standing issue noting this misalignment, how should we deal with this? I can move this and the sprintf
segfault workarounds to local patches in the Termux repo, as they only affect native Android/x64 builds, not cross-compiling. Don't want to clutter LDC up with hacks for such a niche platform as Android/x64.
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.
Seems like a good reason to finally fix it, at least partially. As making sure scope
allocations use the actual class alignment seems to be enough in this case, that'd be a good start.
dmd/cppmangle.d
Outdated
@@ -1196,7 +1196,7 @@ extern(C++): | |||
case Tint128: c = 'n'; break; | |||
case Tuns128: c = 'o'; break; | |||
case Tfloat64: c = 'd'; break; | |||
case Tfloat80: c = 'e'; break; | |||
case Tfloat80: c = 'g'; break; |
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.
Along with using __float128
comes its own mangle, as can be seen in the comment block above, but only for Android/x64, llvm-mirror/clang@309b490. I guess I'll have to add a global.params.isAndroid
and change this for the Android/x64 target alone.
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.
Yep.
dmd/dmangle.d
Outdated
@@ -913,7 +913,7 @@ public: | |||
{ | |||
enum BUFFER_LEN = 36; | |||
char[BUFFER_LEN] buffer; | |||
const n = CTFloat.sprint(buffer.ptr, 'A', value); | |||
const n = CTFloat.sprint(buffer.ptr, 'g', value); |
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.
sprintf
/printf
from Bionic/x64 segfault for certain long double
values passed to them with the hex format, at least in the Anbox Android/x64 environment I'm testing in, termux/termux-packages#3058. Maybe they gave up on implementing hex formatting in Bionic, as they simply closed this issue, android/ndk#437, and the Termux issue shows the garbled output on AArch64 too.
At least it doesn't segfault on AArch64, so the tests still pass, whereas a few tests in std.conv
and std.algorithm.iteration
get ldc to segfault in this sprintf
when it's passed some floating-point numbers, such as 1.414
. Simply using decimal formatting works around the Android/x64 bug.
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.
No TLS support, no/buggy hex string <-> FP conversion... seriously? And then 128-bit software long double
- I find Bionic pretty ridiculous as C runtime in 2018 created by one of the biggest software companies.
dmd/cppmangle.d
Outdated
case Tfloat80: c = 'e'; break; | ||
case Tfloat80: | ||
// LDC: `long double` on Android/x64 is __float128 and mangled as `g`. | ||
c = global.params.isAndroid && isArchx86_64() ? 'g' : 'e'; |
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.
Apparently Kai added this before but Iain removed it, dlang/dmd#6887, because GDC probably doesn't reuse Tfloat80
for 128-bit floats, so this doesn't hit and goes to the Target.cppTypeMangle
in the default case below instead.
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.
That is probably preferable; the C++ mangling of Tfloat80
representing D real
/ C++ long double
is target-specific with this now too (and most likely would be for proper PowerPC support too).
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.
Updated, let me know if this new commit is what you had in mind, passes the tests.
I'd prefer |
Alright, changed the mangling in the file you wanted. Ignore the Phobos commits, that's not going to be in the final version of this pull. I simply figured that if this pull is going to kick off a Shippable build, might as well take advantage and check some AArch64 stuff too. |
Thx; I re-added the (versioned-out) upstream |
So this is still working as intended with |
Haven't checked on Android/x64 yet with your changes or those additional cases, also want to get the std.variant/math issues ironed out. Need to look into those. |
Alright, looked into the OK, that's expected given the union it's using, so I tried sticking an Not unexpected given the union and all the casts I see scattered around, but not sure the best way to fix this. I guess |
Regarding the last
It works if I use the straight D bit-casting version just below or replace @kinke, you know this stuff best, what do you suggest? |
Yeah, that's definitely a bug in that
Seems like LLVM reasonably doesn't expect an |
Like this? All |
…re.sys.posix.sys.stat.stat_t.
Pulled in the upstream Phobos commits too, will check those Android/x64 ABI cases you mentioned and this should be ready to go. Once LLVM 7.0.1 is out, release 1.13 this weekend? |
Yeah, that'd be the current plan. |
Alright, looked over your commit and checked those other Android/x64 mangles: |
The mangling adaptation introduced a regression wrt. backreferences (see https://forum.dlang.org/thread/[email protected]): extern(C++) real _modulo(real x, real y);
pragma(msg, _modulo.mangleof);
|
--> #2953 |
Android/x64 mostly works, but has some issues because of their unusual choice of having
long double
be a__float128
, likely to match AArch64.I'm getting this up early to get feedback. There's also two issues with Phobos I'll look into:
std.math.copysign
won't compile withllvm_copysign
on both x86 and x64 and many of thestd.variant
tests segfault on x64.Otherwise, only a few tests fail, mostly the same ones as on AArch64 because of a couple trailing bits or missing IEEE Quadruple support: