| 1 |
/* dalloca.h - alloca function for tinycc which doesn't have one natively |
| 2 |
* $Id: dalloca.h,v 1.2 2003/06/01 01:01:47 joshk Exp $ |
| 3 |
*/ |
| 4 |
|
| 5 |
/* |
| 6 |
* Copyright (C) 2003 Damian M Gryski <dgryski@uwaterloo.ca> |
| 7 |
* Released under LGPL 2.1 |
| 8 |
*/ |
| 9 |
|
| 10 |
#ifdef __TINYC__ |
| 11 |
|
| 12 |
#ifdef NO_ALLOCA_CHECK |
| 13 |
#define alloca_assert(expr) |
| 14 |
#else |
| 15 |
#include <assert.h> |
| 16 |
#define alloca_assert(expr) assert(expr) |
| 17 |
#endif |
| 18 |
|
| 19 |
/* |
| 20 |
* `size' is known at compile time, but tccasm doesn't like the math expr. |
| 21 |
* Blindly accept input, but at least assert() that it's good. |
| 22 |
* Since the assert() check is substantially more expensive than the alloca |
| 23 |
* itself, the check can be turned off by compiling with -DNO_ALLOCA_CHECK |
| 24 |
*/ |
| 25 |
|
| 26 |
#define alloca_const(size) \ |
| 27 |
({ void * __sp; \ |
| 28 |
alloca_assert(size % 4 == 0); \ |
| 29 |
asm("subl $" #size ", %%esp\n" \ |
| 30 |
"movl %%esp, %0" \ |
| 31 |
: "=m" (__sp) ) ; \ |
| 32 |
__sp; }) |
| 33 |
|
| 34 |
#define alloca_var(size) \ |
| 35 |
({ void * __sp; unsigned int __arg = size; \ |
| 36 |
asm("movl %1, %%eax\n" /* get the size */ \ |
| 37 |
"addl $3, %%eax\n" /* eax := (eax + 3) & -4 */ \ |
| 38 |
"andl $-4, %%eax\n" /* rounds to next multiple of 4 */ \ |
| 39 |
"subl %%eax, %%esp\n" /* adjust stack pointer */ \ |
| 40 |
"movl %%esp, %0\n" /* return result */ \ |
| 41 |
: "=m" (__sp) : "m" (__arg) : "eax") ; \ |
| 42 |
__sp ; }) |
| 43 |
|
| 44 |
|
| 45 |
#define alloca(size) alloca_var(size) |
| 46 |
|
| 47 |
#endif |