On x86_64, a proper solution (see GitHub #120) is still needed,
but this will have to wait until the special case for extern(D)
is gone from the implementation.
We need this right now as std.digest.md in 2.061 triggers a
miscompilation issue in the LLVM x86 backend (not the optimizer!)
when returning them directly as LLVM arrays.
The solution is to replace Attribute with AttrBuilder in IrFuncTyArg.
Then the argument attributes can be easily manipulated and transformed
into the final AttributeSet.
This is based on Item 2 of "More Effective C++". In general, the C++ cast operators are more expressive and easy to find,
e.g. by grep. Using const_cast also shuts up some compiler warnings.
crucial difference being special handling of `llvm::Type`s so they get printed
by name rather than printing their full representation (which can be positively
*huge*).
This allows re-enabling some logger calls that were disabled due to extreme
verbosity.
Applied function type from D1 frontend that got removed in D2, it's critical for member function type to be correct.
Fixed a bunch of type discrepancies in druntime object.di vs. genobj.d .
Disabled (#if 0) some potentally very large type dumps for -vv .
Updated classinfo and typeinfo generation for D2, almost complete now.
Added finer grained checks for vtbl type mismatching, aids debugging.
are available for extern(C) functions on x86-64.
Interestingly, llvm-g++ seems to have a very similar bug: http://llvm.org/pr4242
(So this breaks ABI-compatibility with llvm-gcc for this corner case, but gains
it with gcc...)
To clarify, this is about code like this:
{{{
struct S { void*[3] data; }
struct T { void*[2] data; }
// The T should be passed in memory, and p in the last int register.
extern(C) S fail(int, int, int, int, T t, void* p) {
S s;
s.data[0] = t.data[0];
s.data[1] = t.data[1];
s.data[2] = p;
return s;
}
}}}
which should generate code functionally equivalent to this:
{{{
extern(C) S* succeed(S* s, int, int, int, int, T t, void* p) {
s.data[0] = t.data[0];
s.data[1] = t.data[1];
s.data[2] = p;
return s;
}
}}}
(with the same definitions for S and T)
be a problem.
As noted before, this will break ABI-compatibility on x86-64, so recompile old
code before linking with newly-compiled code if you're on x86-64.
As an added bonus, I actually tested it this time :).
between different LLVM versions.
This means LLVM r67588 is required if you want to compile for x86-64, otherwise
the backend will assert when you try to return e.g. struct { int i; char c; }
from a function. (In particular, this is no longer compatible with LLVM 2.5)
It also means that any code returning small structs on x86-64 will probably
need to be recompiled in order to be linkable to code compiled with this change.
conditionally removing the workaround makes the ABI dependent on LLVM version,
I reconsidered that.
(The same revision of LDC compiling for the same target should probably produce
code that follows the same ABI, right?)
(LLVM abort()s in codegen if the second integer in a return value is <= i8 on
x86/x86-64)
This was breaking native compilation of Tango's TempFile module on x86-64.
I made sure to create a merge conflict with the code attached to ticket #229
(which comments this code out due to changes in the DMD 'Type' type hierarchy)
so that if it gets committed as-is there will be a human looking at it.
- See through typedefs and enums in passByVal
- Don't depend on TypeFunction::parameters->dim being the actual number of
parameters; it contains unexpanded tuples as single elements.
- Implement x86-64 extern(C), hopefully correctly.
- Tried to be a bit smarter about extern(D) while I was there.
Interestingly, this code seems to be generating more efficient code than
gcc and llvm-gcc in some edge cases, like returning a `{ [7 x i8] }` loaded from
a stack slot from an extern(C) function. (gcc generates 7 1-byte loads, while
this code generates a 4-byte, a 2-byte and a 1-byte load)
I also added some changes to make sure structs being returned from functions or
passed in as parameters are stored in memory where the rest of the backend seems
to expect them to be. These should be removed when support for first-class
aggregates improves.