5.4.2.2 Automatic Storage Duration Objects

Objects with automatic storage duration, such as auto, parameter objects, and temporary variables, are typically allocated space on a stack implemented by the compiler.

MPLAB XC8 has two stack implementations: a compiled stack and a software stack (described in 5.7.2 Data Stacks). Each C function is compiled to use exactly one of these stacks for its automatic storage duration objects and the table below summarizes how the choice of stack affects a function’s reentrancy.

Table 5-7. Function Models Implementation
Data Stack Used Function Model Supported Device Families
Compiled stack Non-reentrant All devices
Software stack Reentrant Enhanced Mid-range and PIC18 devices

When compiling for those devices that do not support the reentrant function model, all functions are encoded to use the compiled stack, which are non-reentrant functions.

For the Enhanced Mid-range and PIC18 devices, by default the compiler will use the non-reentrant model for all functions. The -mstack option (see 4.6.1.23 Stack Option) can be used to change the compiler’s default behavior when assigning function models. Select the software argument with this option so that the compiler will always choose the reentrant model (software stack) for each function. Set this option to hybrid to allow the compiler to decide how each function should be encoded. If the function is not reentrantly called, then it will be encoded to use the non-reentrant model and the compiled stack. If the function appears in more than one call graph (i.e., it is called from main-line and interrupt code), or it appears in a loop in a call graph (i.e., it is called recursively), then the compiler will use the reentrant model. The hybrid mode allows the program to use recursion but still take advantage of the more efficient compiled stack.

Alternatively you can change the function model for individual functions by using function specifiers when you define the function. Use either the __compiled or __nonreentrant specifier (identical meanings) to indicate that the specified function must use the compiled stack, without affecting any other function. Alternatively, use either the __software or __reentrant specifier to indicate a function must be encoded to use the software stack.

The function specifiers have precedence over the -mstack option setting. If, for example, the option -mstack=compiled has been used, but one function uses the __software (or __reentrant) specifier, then the specified function will use the software stack and all the remaining functions will use the compiled stack. These functions specifiers also override any choice made by the compiler in hybrid mode.

If the -mstack=compiled option has been issued or a function has been specified as __compiled (or __nonreentrant) and that function appears in more than one call graph in the program, then a function duplication feature automatically comes into effect (see 5.9.7 Function Duplication). Duplicating a non-reentrant function allows it to be called from multiple call graphs, but cannot allow the function to be called recursively.

The auto objects defined in a function will not necessarily be allocated memory in the order declared, in contrast to parameters which are always allocated memory based on their lexical order. In fact, auto objects for one function can be allocated in many RAM banks.

The standard const qualifier can be used with auto objects and forces them to be read-only. These objects, however, might not be stored on the stack. See 5.1.2.4 Const Auto Objects for how the compiler allocates such objects.