NOTICE: The Processors Wiki will End-of-Life on January 15, 2021. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.
GNU alloca in TI Compilers
Contents
What is alloca
?[edit]
<syntaxhighlight lang="cpp" line="normal" start=1 strict enclose="div" header="" footer=""> void *alloca(size_t sz); </syntaxhighlight>
alloca
is a builtin function provided by the GNU Compiler Collection (gcc) for compatibility with older C code. It has the following behavior:
- The function allocates memory according to the value of
sz
and returns a pointer to the beginning of the allocated memory - A failed attempt to allocate memory results in undefined behavior
- The memory is automatically deallocated on function exit
alloca
in TI Compilers[edit]
The TI Compiler does not support alloca
, but rather suggests safer or more elegant solutions.
In the following example, alloca
is used to allocate a storage array which then stores gathered data before being condensed to a single value which is returned. After this function exits, the memory associated with store_array will be reclaimed.
<syntaxhighlight lang="cpp" line="normal" start=1 strict enclose="div" header="" footer=""> int process_data(int n) { int i; int *store_array = alloca(n * sizeof(int)); for (i = 0; i < n; i++) { store_array[i] = gather_some_data(); }
return condense_data(store_array); } </syntaxhighlight>
Replacement with malloc
[edit]
A safer alternative to alloca in most code is to just not use it. Though stack-based implementations are faster, replacing alloca
with malloc
will allow the TI compiler to compile the code, and will also make the code more explicit about where memory is deallocated.
<syntaxhighlight lang="cpp" line="normal" start=1 strict enclose="div" header="" footer=""> int process_data(int n) { int i, condensed_value; int *store_array = malloc(n * sizeof(int)); for (i = 0; i < n; i++) { store_array[i] = gather_some_data(); }
condensed_value = condense_data(store_array); free(store_array);
return condensed_value; } </syntaxhighlight>
Variable Length Arrays[edit]
C99 includes a feature called variable length arrays (VLAs) which can also perform this task, and is also supported by the TI compiler in strict C99 mode or relaxed C/C++ modes. With VLAs, the code above could be rewritten into the following.
<syntaxhighlight lang="cpp" line="normal" start=1 strict enclose="div" header="" footer=""> int process_data(int n) { int i; int store_array[n]; for (i = 0; i < n; i++) { store_array[i] = gather_some_data(); }
return condense_data(store_array); } </syntaxhighlight>
The difference between VLAs and the alloca
function is that the storage associated with a VLA is reclaimed when the variable goes out of scope rather than on function exit.
Below is a list of compiler versions in which VLAs are first available.
ISA | Version |
---|---|
ARM | 5.1 |
C2000 | 6.2 |
MSP430 | 4.2 |
alloca
Emulation[edit]
If refactoring code to not use alloca
is infeasible, for example in ported code, then there are public implementations of alloca which can be compiled and linked into your project to emulate the function. Note that this code is provided as-is, and is not officially supported by TI.
First, provide the signature in application code for alloca
:
<syntaxhighlight lang="cpp" line="normal" start=1 strict enclose="div" header="" footer="">
void *alloca(size_t sz);
</syntaxhighlight>
Then, compile alloca.c either separately or during a build and use the object file to link the function into your executable. This enables alloca
to be emulated with TI compilers.
The main deficiency in this approach is that storage is only deallocated when alloca
is called from a function scope whose call depth is lower. That is to say, memory is not deallocated at the end of a function, but rather whenever alloca
is called after the function exits. An example of this behavior is exhibited in the following code segment.
<syntaxhighlight lang="cpp" line="normal" start=1 strict enclose="div" header="" footer="">
void foo(int x)
{
int *ptr = alloca(x);
}
int main() { int i; for (i = 1; i < 100; i++) { foo(i) } } </syntaxhighlight>
The space allocated to ptr
in foo
is never deallocated, which conflicts with the definition of alloca
. The only solution to this issue is to make a call to alloca(0)
after foo
's call in the for loop. alloca(0)
just runs garbage collection and does not allocate any space.
==