https://issues.dlang.org/show_bug.cgi?id=16856
Nemanja Boric <4bur...@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |4bur...@gmail.com --- Comment #4 from Nemanja Boric <4bur...@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? --