Typesafe align macros

This commit is contained in:
Nils O. Selåsdal
2026-06-10 20:25:47 +02:00
parent 0fbe5e8255
commit a21311de7b
+37 -6
View File
@@ -104,12 +104,43 @@ typedef unsigned __int128 U128;
(const type *)((const void *)(const unsigned char *)__mptr - offsetof(const type, member)); \
})
// align needs to be pow2
#define AlignUp(val, align) (((val) + (align) - 1UL) & ~((align) - 1UL))
#define AlignDown(val, align) ((val) & ~((align) - 1UL))
#define IsPow2(x) ((x) && !((x) & ((x) - 1UL)))
#define IsPow2OrZero(x) (!((x) & ((x) - 1UL)))
#define IsAlignedTo(x, align) (IsPow2(align) && !((x) & ((align) - 1UL)))
// `align` must be a power of two.
//
// These keep the result in the *same integer type as the first argument*
#define AlignUp(val, align) \
({ \
__typeof__(val) AlignUp_v_ = (val); \
__typeof__(val) AlignUp_a_ = (__typeof__(val))(align); \
(__typeof__(val))((AlignUp_v_ + (AlignUp_a_ - 1)) & \
~(__typeof__(val))(AlignUp_a_ - 1)); \
})
#define AlignDown(val, align) \
({ \
__typeof__(val) AlignDown_v_ = (val); \
__typeof__(val) AlignDown_a_ = (__typeof__(val))(align); \
(__typeof__(val))(AlignDown_v_ & ~(__typeof__(val))(AlignDown_a_ - 1));\
})
#define IsPow2(x) \
({ \
__typeof__(x) IsPow2_x_ = (x); \
IsPow2_x_ && !(IsPow2_x_ & (__typeof__(x))(IsPow2_x_ - 1)); \
})
#define IsPow2OrZero(x) \
({ \
__typeof__(x) IsPow2OrZero_x_ = (x); \
!(IsPow2OrZero_x_ & (__typeof__(x))(IsPow2OrZero_x_ - 1)); \
})
#define IsAlignedTo(x, align) \
({ \
__typeof__(x) IsAlignedTo_x_ = (x); \
__typeof__(x) IsAlignedTo_a_ = (__typeof__(x))(align); \
IsPow2(IsAlignedTo_a_) && \
!(IsAlignedTo_x_ & (__typeof__(x))(IsAlignedTo_a_ - 1)); \
})
#define GetBit(val, idx) (((val) >> (idx)) & 1)
// Get n_bits starting at idx going left