4.6.1.24 Stack Option

The -mstack=model[:size|auto] option selects the default stack model to be used by a program, which will dictate which stack will be used for functions that do not use a stack specifier. Additionally, it can specify the size of memory reserved for the software stack.

Functions can use stack specifiers (described in Reentrant And Nonreentrant Specifiers) to indicate which stack should be used for that function's stack-based variables. For functions that do not use these specifiers, the -mstack option controls the stack type that the compiler will use.

The two data stacks available are called a compiled stack and a software stack. Objects destined for the software stack might be allocated to working registers in a register-optimized reentrant stack (if that feature is enabled, see Rors Option) at the compiler's discretion, but still fall under the software stack model. See Data Stacks for more information on storage of stack-based objects. The stack models that can be used with this option are described in the table below.

Table 4-13. Stack Suboptions
ModelDefault Allocation for Stack-based Variables
compiled or nonreentrantUse the compiled stack for all functions not using a stack specifier; these functions will then be non-reentrant.
software or reentrantUse the software and/or register-optimized reentrant stack for functions not using a stack specifier; these functions will then be reentrant.
hybridFor functions not using a stack specifier, choose a stack type based on how that function is called and referenced in the program.

If the -mstack option is not used, all functions not using a stack specifier will use the compiled stack and be non-reentrant.

The software (or reentrant) or hybrid models have no effect on projects targeting baseline and mid-range devices, as these devices only support a compiled stack. Interrupt functions might save context to the software stack when using the hybrid or reentrant models, however they will must the compiled stack for autos they define. Functions called by an interrupt function may use the software stack.

The hybrid model (-mstack=hybrid) will let the compiler choose how to encode each function based on how it is called. See Automatic Storage Duration Objects for more information on what factors the compiler considers when making this choice. This model allows for reentrancy, when required, but takes advantage of the efficiency of the compiled stack for the majority of the program’s functions.

Note: Use the software (reentrant) setting with caution. The maximum runtime size of the software stack is not accurately known at compile time, so the compiler cannot predict an overflow, which could corrupt objects or registers. When all functions are forced to use the software stack, the stack size might increase substantially. Code to access objects on a software stack is typically larger than that used to access objects on a compiled stack.

In addition to the stack model, the -mstack option can be used to specify the maximum size of memory reserved by the compiler for the software stack. This option configuration only affects the conventional software stack; it does not affect the number or allocation of working registers in the register-optimized reentrant stack. Nor can this form of the option be used to change the amount of available memory for the compiled stack, which is fixed and known at compile time.

Distinct software stacks are created for use by main-line code and interrupt functions, but this is transparent at the program level. In the case of PIC18 devices, separate stacks are created for high- and low-priority interrupts (along with one for main-line code), each interrupt stack available for all interrupt functions associated with an interrupt source set to that priority. So, for example, if you are using a PIC18 device with the vectored interrupt controller enabled, each reentrant interrupt function defined using the __high_priority keyword will use the software stack devoted to high-priority interrupts. The compiler automatically manages the allocation of memory to each stack. If your program does not define any interrupt functions, all the available memory can potentially be made available to the software stack used by main-line code.

The maximum space the compiler will attempt to reserve for each area of the stack can be specified by following the reentrant stack type with a colon-separated list of decimal values, each being the size, in bytes, of the memory to be reserved. The sizes specified in the option correspond in this order to: the main-line code, the low-priority interrupt and the high-priority interrupt. For example the option:
-mstack=reentrant:200:0:40
when used with PIC18 projects will attempt to reserve 200 bytes for the main-line stack, zero bytes for the low-priority interrupt stack, and 40 bytes for the high-priority interrupt stack. At runtime, the stacks will be able to grow to the specified sizes with no corruption of data. This memory is reserved unconditionally, even if no reentrant functions are present in the program.
Alternatively, any size argument may be specified as auto, in which case the compiler will calculate a maximum size for this stack after other static, stack, and heap allocations have been made. Memory with this calculated size will only be reserved, however, if the compiler detects the presence of any function using a reentrant stack. If no -mstack option is specified, then the compiler uses an auto setting for every stack that can be potentially used by the program. Whenever acting with an auto stack size setting, the compiler will issue a compiler advisory message if reentrant functions have been detected and memory has been reserved as a result. For PIC18 devices, the following example:
-mstack=reentrant:auto:30:50
will arrange the stack starting locations so that the low-priority interrupt stack can grow to at most 30 bytes (before overflow); the high-priority interrupt stack can grow to at most 50 bytes (before overflow); and the main-line code stack can consume the remainder of the free memory after other static, stack, and heap allocations have been made. If you are not using an interrupt, it is recommended that you explicitly set the unused interrupt stack size to zero using this option.

If the maximum stack sizes are specified with this option, each size must be a numerical value or the auto token; do not leave a size field empty. If the sizes specified in this option would allocate more stack memory than is available, a warning will be issued and only the available memory will be utilized.

The size of the heap used by dynamic memory allocation functions is also dynamic in nature, and memory must be reserved for its use. That memory is specified using the -mheap option (see Heap Option). A size argument of auto can be used with both the -mstack and -mheap options, in which case the compiler will evenly distribute the free memory remaining between the heap and stacks after statically allocated objects have been placed.