diff --git a/hpy/devel/src/runtime/ctx_type.c b/hpy/devel/src/runtime/ctx_type.c index 59432814b..e553dc8ea 100644 --- a/hpy/devel/src/runtime/ctx_type.c +++ b/hpy/devel/src/runtime/ctx_type.c @@ -4,6 +4,31 @@ #include "hpy.h" #include "hpy/runtime/ctx_type.h" +/* Since C11, there is type 'max_align_t' which is defined as: 'max_align_t' is + a type whose alignment requirement is at least as strict (as large) as that + of every scalar type. + Also, pointers returned by allocation functions such as malloc are suitably + aligned for any object, which means they are aligned at least as strictly as + 'max_align_t'. + We use sizeof(max_align_t) to align pure HPy type data pointers. + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define MAX_ALIGN_SIZE sizeof(max_align_t) +#else +/* Before C11, we do not have 'max_align_t' but it is usually synonymous with + the largest scalar type, which is 'long double' on most platforms. So, this + is best effort. + */ +#define MAX_ALIGN_SIZE sizeof(long double) +#endif + +/* Macro ALIGN_SIZE aligns a given size to a multiple of the provided + alignment. We apply this macro to the inherited basicsize such that the + appended data will have an aligned data pointer. For example, if we would + get a inherited basicsize of 11 and the aligment is 16 bytes, then + ALIGN_SIZE(16, 11) == 16. Picking the right alignment is crucial! */ +#define ALIGN_SIZE(_align, _size) ((HPy_ssize_t)((((uintptr_t)(_size)) - 1u + (_align)) & -(_align))) + #ifdef HPY_UNIVERSAL_ABI // for _h2py and _py2h # include "handles.h" @@ -959,6 +984,7 @@ ctx_Type_FromSpec(HPyContext *ctx, HPyType_Spec *hpyspec, base_member_offset = compute_largest_basicsize(bases); if (base_member_offset < 0) return HPy_NULL; + base_member_offset = ALIGN_SIZE(MAX_ALIGN_SIZE, base_member_offset); if (base_member_offset > INT_MAX) Py_FatalError("basicsize is too large"); }