openMSX
vla.hh
Go to the documentation of this file.
1#ifndef VLA_HH
2#define VLA_HH
3
4#include <span>
5
6// VLAs (Variable Length Array's) are part of C99, but not of C++98.
7// Though gcc does support VLAs as an extension. For VC++ we have to emulate
8// them via alloca.
9
10#ifndef _MSC_VER
11
12#define VLA(TYPE, NAME, LENGTH) \
13 TYPE NAME##_storage[(LENGTH)]; \
14 std::span NAME{NAME##_storage, size_t(LENGTH)}
15
16#if defined __i386 || defined __x86_64
17#define VLA_ALIGNED(TYPE, NAME, LENGTH, ALIGNMENT) \
18 TYPE NAME##_storage[(LENGTH)] __attribute__((__aligned__((ALIGNMENT)))); \
19 std::span NAME{NAME##_storage, size_t(LENGTH)}
20#else
21// Except on x86/x86-64, GCC can align VLAs within a stack frame, but it makes
22// no guarantees if the requested alignment is larger than the alignment of the
23// stack frame itself.
24// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
25#define VLA_ALIGNED(TYPE, NAME, LENGTH, ALIGNMENT) \
26 UNABLE_TO_GUARANTEE_VLA_ALIGNMENT_ON_THIS_ARCHITECTURE
27#endif
28
29#else
30
31#define VLA(TYPE, NAME, LENGTH) \
32 auto NAME##_storage = static_cast<TYPE*>(_alloca(sizeof(TYPE) * (LENGTH))); \
33 std::span NAME{NAME##_storage, size_t(LENGTH)}
34
35// mfeingol: evil hack alert
36#define VLA_ALIGNED(TYPE, NAME, LENGTH, ALIGNMENT) \
37 size_t cbAlign##NAME = (ALIGNMENT); \
38 void* palloc##NAME = _alloca(sizeof(TYPE) * (LENGTH) + cbAlign##NAME); \
39 palloc##NAME = (void*)((size_t(palloc##NAME) + cbAlign##NAME - 1UL) & ~(cbAlign##NAME - 1UL)); \
40 auto NAME##_storage = static_cast<TYPE*>(palloc##NAME); \
41 std::span NAME{NAME##_storage, size_t(LENGTH)}
42
43#endif
44
45// Macro to align a buffer that might be used by SSE instructions.
46// On platforms without SSE no (extra) alignment is performed.
47#ifdef __SSE2__
48#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH) VLA_ALIGNED(TYPE, NAME, LENGTH, 16)
49#else
50#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH) VLA(TYPE, NAME, LENGTH)
51#endif
52
53#endif // VLA_HH