/* 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)