5.9.7 Function Duplication

MPLAB XC8 compiler employs a feature that duplicates the generated code associated with any function that uses a non-reentrant model and that is called from more than one call graph.

There is one call graph associated with main-line code and one for each interrupt function, if defined. The compiler assumes that interrupts can occur at any time. Functions encoded to use the compiled stack are not reentrant, thus such functions called from main-line code and from interrupt code could result in code failure. The compiler will duplicate the output for any non-reentrant function called from more than one call graph. This makes the function appear to be reentrant; however, recursion is still not possible.

Although the compiler could alternatively compile functions using a reentrant model, this feature is not available with all devices and the code might be less efficient. In addition, the -mstack option or the __nonreentrant specifier can be used to prevent the compiler from choosing this model. See 6.3.3 Function Information to determine which function model was used for each function.

If a function is duplicated, main-line code will call the code generated for the original function and code in each interrupt call graph will call a unique duplicated function. The duplication takes place only in the generated code output; there is no duplication of the C source code itself.

The duplicated code and objects defined by the function use unique identifiers. A duplicate identifier is identical to that used by the original code, but is prefixed with i1. Duplicated PIC18 functions use the prefixes i1 and i2 for the low- and high-priority interrupts, respectively.

To illustrate, in a program both the function main() and a function in interrupt code call a function called input(). The generated assembly code for the C function input() will use the assembly label _input. The corresponding label used by the duplicated function output will be i1_input. If input() makes reference to a temporary variable, the generated code will use the symbol ??_input and the duplicate will use ??i1_input. Even local labels within the function’s generated code will be duplicated in the same way. The call graph in the assembly list file, will show the calls made to both of these functions as if they were independently written. These symbols will also be seen in the map file symbol table.

Code associated with library functions are duplicated in the same way. This also applies to implicitly-called library routines, such as those that perform division or floating-point operations associated with C operators.