/* dalloca.h */
/*
* Copyright (C) 2003 Damian M Gryski
* Released under LGPL 2.1
*/
#if __TINYC__
#ifdef NO_ALLOCA_CHECK
#define alloca_assert(expr)
#else
#include
#define alloca_assert(expr) assert(expr)
#endif
/*
* `size' is known at compile time, but tccasm doesn't like the math expr.
* Blindly accept input, but at least assert() that it's good.
* Since the assert() check is substantially more expensive than the alloca
* itself, the check can be turned off by compiling with -DNO_ALLOCA_CHECK
*/
#define alloca_const(size) \
({ void * __sp; \
alloca_assert(size % 4 == 0); \
asm("subl $" #size ", %%esp\n" \
"movl %%esp, %0" \
: "=m" (__sp) ) ; \
__sp; })
#else
/*
* we can round `size' at compile time to make sure %esp stays aligned
*/
#define alloca_const(size) \
({ void * __sp; \
asm("subl $ (" #size " + 3) & -4, %%esp\n" \
"movl %%esp, %0" \
: "=m" (__sp) ) ; \
__sp; })
#endif
/*
* `size' not known at compile time -- round it at runtime
*/
#define alloca_var(size) \
({ void * __sp; unsigned int __arg = size; \
asm("movl %1, %%eax\n" /* get the size */ \
"addl $3, %%eax\n" /* eax := (eax + 3) & -4 */ \
"andl $-4, %%eax\n" /* rounds to next multiple of 4 */ \
"subl %%eax, %%esp\n" /* adjust stack pointer */ \
"movl %%esp, %0\n" /* return result */ \
: "=m" (__sp) : "m" (__arg) : "eax") ; \
__sp ; })
/* by default, don't assume we know size at compile time */
#define alloca(size) alloca_var(size)