[Issue 16856] D does not work on FreeBSD current (what will eventually be 12) due to libunwind
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Sun May 7 06:23:59 PDT 2017
https://issues.dlang.org/show_bug.cgi?id=16856
Nemanja Boric <4burgos at gmail.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |4burgos at gmail.com
--- Comment #4 from Nemanja Boric <4burgos at gmail.com> ---
I've looked into this, and this is the alignment issue.
The faulty instruction happens here:
https://github.com/llvm-mirror/libunwind/blob/master/src/UnwindLevel1.c#L351
```
exception_object->private_1 = 0;
```
On FreeBSD-Current, this is executed as:
```
xorps xmm0, xmm0
movaps XMMWORD PTR [r14+0x10], xmm0
```
where r14 is the pointer to the Unwind_Exception
(https://github.com/llvm-mirror/libunwind/blob/master/include/unwind.h#L119-L124)
or D runtime part:
(https://github.com/dlang/druntime/blob/master/src/rt/unwind.d#L51-L57)
```
struct _Unwind_Exception
{
align(8) _Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
_Unwind_Word private_1;
_Unwind_Word private_2;
}
```
or
```
struct _Unwind_Exception {
uint64_t exception_class;
void (*exception_cleanup)(_Unwind_Reason_Code reason,
_Unwind_Exception *exc);
uintptr_t private_1; // non-zero means forced unwind
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#ifndef __LP64__
// The implementation of _Unwind_Exception uses an attribute mode on the
// above fields which has the side effect of causing this whole struct to
// round up to 32 bytes in size. To be more explicit, we add pad fields
// added for binary compatibility.
uint32_t reserved[3];
#endif
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
// aligned". GCC has interpreted this to mean "use the maximum useful
// alignment for the target"; so do we.
} __attribute__((__aligned__));
```
Now, this happens because `movaps` instruction requires 16-bit aligned memory,
which is not the case for _Unwind_Exceptin.private_1 - where it is aligned to 8
bits.
Making D definition to align this instance (at least D-allocated) to 16 bits
fixes the entire problem - exception handling works:
```
align(16)
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
_Unwind_Word private_1;
_Unwind_Word private_2;
}
```
Now, the problem is that I don't know how to effectively calculate the
alignment and do whatever the C++ compiler would do. I guess this is necessity,
because we want C++ exceptions (generated by the C++ compiler) to work.
GCC documentation is stating:
https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html
```
As in the preceding example, you can explicitly specify the alignment (in
bytes) that you wish the compiler to use for a given struct or union type.
Alternatively, you can leave out the alignment factor and just ask the compiler
to align a type to the maximum useful alignment for the target machine you are
compiling for. For example, you could write:
struct S { short f[3]; } __attribute__ ((aligned));
Whenever you leave out the alignment factor in an aligned attribute
specification, the compiler automatically sets the alignment for the type to
the largest alignment which is ever used for any data type on the target
machine you are compiling for. Doing this can often make copy operations more
efficient, because the compiler can use whatever instructions copy the biggest
chunks of memory when performing copies to or from the variables which have
types that you have aligned this way.
In the example above, if the size of each short is 2 bytes, then the size of
the entire struct S type is 6 bytes. The smallest power of two which is greater
than or equal to that is 8, so the compiler sets the alignment for the entire
struct S type to 8 bytes.
```
Any ideas?
--
More information about the Digitalmars-d-bugs
mailing list