@@ -300,9 +300,10 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t sz,
300
300
}
301
301
302
302
// Determine if homogeneous tuple with fields of type t will have
303
- // a special alignment beyond normal Julia rules.
303
+ // a special alignment and vector-ABI beyond normal rules for aggregates .
304
304
// Return special alignment if one exists, 0 if normal alignment rules hold.
305
305
// A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
306
+ // Matching the compiler's `__attribute__ vector_size` behavior.
306
307
// For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
307
308
// without LLVM being available.
308
309
unsigned jl_special_vector_alignment (size_t nfields , jl_value_t * t )
@@ -317,8 +318,12 @@ unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
317
318
// motivating use case comes up for Julia, we reject pointers.
318
319
return 0 ;
319
320
size_t elsz = jl_datatype_size (ty );
320
- if (elsz != 1 && elsz != 2 && elsz != 4 && elsz != 8 )
321
- // Only handle power-of-two-sized elements (for now)
321
+ if (next_power_of_two (elsz ) != elsz )
322
+ // Only handle power-of-two-sized elements (for now), since other
323
+ // lengths may be packed into very complicated arrangements (llvm pads
324
+ // extra bits on most platforms when computing alignment but not when
325
+ // computing type size, but adds no extra bytes for each element, so
326
+ // their effect on offsets are never what you may naturally expect).
322
327
return 0 ;
323
328
size_t size = nfields * elsz ;
324
329
// Use natural alignment for this vector: this matches LLVM and clang.
@@ -723,9 +728,9 @@ void jl_compute_field_offsets(jl_datatype_t *st)
723
728
}
724
729
else {
725
730
fsz = sizeof (void * );
726
- if (fsz > MAX_ALIGN )
727
- fsz = MAX_ALIGN ;
728
731
al = fsz ;
732
+ if (al > MAX_ALIGN )
733
+ al = MAX_ALIGN ;
729
734
desc [i ].isptr = 1 ;
730
735
zeroinit = 1 ;
731
736
npointers ++ ;
@@ -769,8 +774,6 @@ void jl_compute_field_offsets(jl_datatype_t *st)
769
774
if (al > alignm )
770
775
alignm = al ;
771
776
}
772
- if (alignm > MAX_ALIGN )
773
- alignm = MAX_ALIGN ; // We cannot guarantee alignments over 16 bytes because that's what our heap is aligned as
774
777
if (LLT_ALIGN (sz , alignm ) > sz ) {
775
778
haspadding = 1 ;
776
779
sz = LLT_ALIGN (sz , alignm );
@@ -939,6 +942,14 @@ JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *
939
942
uint32_t nbytes = (nbits + 7 ) / 8 ;
940
943
uint32_t alignm = next_power_of_two (nbytes );
941
944
# if defined(_CPU_X86_ ) && !defined(_OS_WINDOWS_ )
945
+ // datalayout strings are often weird: on 64-bit they usually follow fairly simple rules,
946
+ // but on x86 32 bit platforms, sometimes 5 to 8 byte types are
947
+ // 32-bit aligned even though the MAX_ALIGN (for types 9+ bytes) is 16
948
+ // (except for f80 which is align 4 on Mingw, Linux, and BSDs--but align 16 on MSVC and Darwin)
949
+ // https://llvm.org/doxygen/ARMTargetMachine_8cpp.html#adb29b487708f0dc2a940345b68649270
950
+ // https://llvm.org/doxygen/AArch64TargetMachine_8cpp.html#a003a58caf135efbf7273c5ed84e700d7
951
+ // https://llvm.org/doxygen/X86TargetMachine_8cpp.html#aefdbcd6131ef195da070cef7fdaf0532
952
+ // 32-bit alignment is weird
942
953
if (alignm == 8 )
943
954
alignm = 4 ;
944
955
# endif
0 commit comments