Skip to content

Commit b308f8c

Browse files
committed
alignment: subtly change meaning of datatype_align
Rather than meaning the actual alignment of the object, this now means the preferred alignment of the object. The actual alignment of any object is the minimum of this preferred alignment and the alignment supported by the runtime allocator. This aligns us with how LLVM treats alignment, and is probably reasonably sensible anyways. Also tries to audit our existing uses of CreateLoad/CreateStore for correctness, and upgrade some to include pointer-types. fixes #32414
1 parent 27f70f8 commit b308f8c

10 files changed

+80
-71
lines changed

base/reflection.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,8 @@ struct DataTypeLayout
319319
nfields::UInt32
320320
npointers::UInt32
321321
firstptr::Int32
322-
alignment::UInt32
323-
# alignment : 9;
322+
alignment::UInt16
323+
flags::UInt16
324324
# haspadding : 1;
325325
# fielddesc_type : 2;
326326
end
@@ -335,7 +335,7 @@ function datatype_alignment(dt::DataType)
335335
@_pure_meta
336336
dt.layout == C_NULL && throw(UndefRefError())
337337
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
338-
return Int(alignment & 0x1FF)
338+
return Int(alignment)
339339
end
340340

341341
# amount of total space taken by T when stored in a container
@@ -368,8 +368,8 @@ Can be called on any `isconcretetype`.
368368
function datatype_haspadding(dt::DataType)
369369
@_pure_meta
370370
dt.layout == C_NULL && throw(UndefRefError())
371-
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
372-
return (alignment >> 9) & 1 == 1
371+
flags = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).flags
372+
return flags & 1 == 1
373373
end
374374

375375
"""
@@ -397,8 +397,8 @@ See also [`fieldoffset`](@ref).
397397
function datatype_fielddesc_type(dt::DataType)
398398
@_pure_meta
399399
dt.layout == C_NULL && throw(UndefRefError())
400-
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
401-
return (alignment >> 10) & 3
400+
flags = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).flags
401+
return (flags >> 1) & 3
402402
end
403403

404404
"""

src/array.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data,
318318
else {
319319
align = elsz = sizeof(void*);
320320
}
321-
if (((uintptr_t)data) & (align - 1))
321+
if (((uintptr_t)data) & ((align > JL_HEAP_ALIGNMENT ? JL_HEAP_ALIGNMENT : align) - 1))
322322
jl_exceptionf(jl_argumenterror_type,
323323
"unsafe_wrap: pointer %p is not properly aligned to %u bytes", data, align);
324324

@@ -385,7 +385,7 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data,
385385
else {
386386
align = elsz = sizeof(void*);
387387
}
388-
if (((uintptr_t)data) & (align - 1))
388+
if (((uintptr_t)data) & ((align > JL_HEAP_ALIGNMENT ? JL_HEAP_ALIGNMENT : align) - 1))
389389
jl_exceptionf(jl_argumenterror_type,
390390
"unsafe_wrap: pointer %p is not properly aligned to %u bytes", data, align);
391391

src/ccall.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ static Value *llvm_type_rewrite(
418418
from = emit_static_alloca(ctx, from_type);
419419
to = emit_bitcast(ctx, from, target_type->getPointerTo());
420420
}
421+
// XXX: deal with possible alignment issues
421422
ctx.builder.CreateStore(v, from);
422423
return ctx.builder.CreateLoad(to);
423424
}
@@ -514,7 +515,7 @@ static Value *julia_to_native(
514515
tbaa_decorate(jvinfo.tbaa, ctx.builder.CreateStore(emit_unbox(ctx, to, jvinfo, jlto), slot));
515516
}
516517
else {
517-
emit_memcpy(ctx, slot, jvinfo.tbaa, jvinfo, jl_datatype_size(jlto), jl_datatype_align(jlto));
518+
emit_memcpy(ctx, slot, jvinfo.tbaa, jvinfo, jl_datatype_size(jlto), julia_alignment(jlto));
518519
}
519520
return slot;
520521
}
@@ -1931,7 +1932,7 @@ jl_cgval_t function_sig_t::emit_a_ccall(
19311932
assert(rtsz > 0);
19321933
Value *strct = emit_allocobj(ctx, rtsz, runtime_bt);
19331934
MDNode *tbaa = jl_is_mutable(rt) ? tbaa_mutab : tbaa_immut;
1934-
int boxalign = jl_datatype_align(rt);
1935+
int boxalign = julia_alignment(rt);
19351936
// copy the data from the return value to the new struct
19361937
const DataLayout &DL = jl_data_layout;
19371938
auto resultTy = result->getType();

src/cgutils.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,8 @@ static unsigned julia_alignment(jl_value_t *jt)
386386
}
387387
assert(jl_is_datatype(jt) && ((jl_datatype_t*)jt)->layout);
388388
unsigned alignment = jl_datatype_align(jt);
389-
assert(alignment <= JL_HEAP_ALIGNMENT);
390-
assert(JL_HEAP_ALIGNMENT % alignment == 0);
389+
if (alignment > JL_HEAP_ALIGNMENT)
390+
return JL_HEAP_ALIGNMENT;
391391
return alignment;
392392
}
393393

@@ -594,7 +594,7 @@ static unsigned jl_field_align(jl_datatype_t *dt, size_t i)
594594
unsigned al = jl_field_offset(dt, i);
595595
al |= 16;
596596
al &= -al;
597-
return std::min(al, jl_datatype_align(dt));
597+
return std::min({al, (unsigned)jl_datatype_align(dt), (unsigned)JL_HEAP_ALIGNMENT});
598598
}
599599

600600
static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isboxed, bool llvmcall)
@@ -636,7 +636,6 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox
636636
if (jst->layout) {
637637
assert(isptr == jl_field_isptr(jst, i));
638638
assert((isptr ? sizeof(void*) : fsz + jl_is_uniontype(ty)) == jl_field_size(jst, i));
639-
assert(al <= jl_field_align(jst, i));
640639
}
641640
Type *lty;
642641
if (isptr) {
@@ -647,8 +646,15 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox
647646
lty = T_int8;
648647
}
649648
else if (jl_is_uniontype(ty)) {
650-
// pick an Integer type size such that alignment will be correct
651-
// and always end with an Int8 (selector byte)
649+
// pick an Integer type size such that alignment will generally be correct,
650+
// and always end with an Int8 (selector byte).
651+
// We may need to insert padding first to get to the right offset
652+
if (al > MAX_ALIGN) {
653+
Type *AlignmentType = ArrayType::get(VectorType::get(T_int8, al), 0);
654+
latypes.push_back(AlignmentType);
655+
al = MAX_ALIGN;
656+
}
657+
assert(al <= jl_field_align(jst, i));
652658
Type *AlignmentType = IntegerType::get(jl_LLVMContext, 8 * al);
653659
unsigned NumATy = fsz / al;
654660
unsigned remainder = fsz % al;
@@ -1212,7 +1218,7 @@ static Value *emit_isconcrete(jl_codectx_t &ctx, Value *typ)
12121218
{
12131219
Value *isconcrete;
12141220
isconcrete = ctx.builder.CreateConstInBoundsGEP1_32(T_int8, emit_bitcast(ctx, decay_derived(typ), T_pint8), offsetof(jl_datatype_t, isconcretetype));
1215-
isconcrete = ctx.builder.CreateLoad(isconcrete, tbaa_const);
1221+
isconcrete = ctx.builder.CreateLoad(T_int8, isconcrete, tbaa_const);
12161222
isconcrete = ctx.builder.CreateTrunc(isconcrete, T_int1);
12171223
return isconcrete;
12181224
}
@@ -1336,7 +1342,7 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j
13361342
//}
13371343
//else {
13381344
load = ctx.builder.CreateAlignedLoad(data,
1339-
isboxed || alignment ? alignment : julia_alignment(jltype),
1345+
isboxed || alignment ? alignment : julia_alignment(jltype),
13401346
false);
13411347
if (aliasscope)
13421348
load->setMetadata("alias.scope", aliasscope);
@@ -2426,7 +2432,8 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo)
24262432
static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, const jl_cgval_t &src, Value *skip, bool isVolatile=false)
24272433
{
24282434
if (AllocaInst *ai = dyn_cast<AllocaInst>(dest))
2429-
ctx.builder.CreateStore(UndefValue::get(ai->getAllocatedType()), ai);
2435+
// TODO: make this a lifetime_end & dereferencable annotation?
2436+
ctx.builder.CreateAlignedStore(UndefValue::get(ai->getAllocatedType()), ai, ai->getAlignment());
24302437
if (jl_is_concrete_type(src.typ) || src.constant) {
24312438
jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ;
24322439
Type *store_ty = julia_type_to_llvm(typ);
@@ -2686,7 +2693,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg
26862693
if (jl_field_isptr(sty, i)) {
26872694
fval = boxed(ctx, fval_info);
26882695
if (!init_as_value)
2689-
tbaa_decorate(tbaa_stack, ctx.builder.CreateStore(fval, dest));
2696+
tbaa_decorate(tbaa_stack, ctx.builder.CreateAlignedStore(fval, dest, jl_field_align(sty, i)));
26902697
}
26912698
else if (jl_is_uniontype(jtype)) {
26922699
// compute tindex from rhs

0 commit comments

Comments
 (0)