I have a pretty big program which shows some very weird behavior during compiling.
Depending on the order in which I included two files, the program either compiled fine or gave a bunch of "L15 Multiple Call to Function" warnings. Each warning had some random function called from main as "NAME" and always "INTERRUPTVECTORS_INT0/MAIN" (see below) as "CALLER1" and "?C_C51STARTUP" as "CALLER2".
The two included files only defined a bunch of functions, none of which did anything noteworthy. Their respective declarations are all in a single file included much earlier. And those functions don't refer to each other.
I merged the two files together and started moving functions around. I narrowed it down to two functions which, when placed in one order, compiled fine, but produced the same warnings when placed in the opposite order. This is one of those two functions:
bit GetSomeBitOfSomeState(unsigned int State, unsigned char BitIndex) { // return (State & (1 << BitIndex)) != 0; return 1 << State; }
Through some trial and error I found that the code, as above, compiled fine (in one order), but replacing "State" with "BitIndex" (which seems like a very mundane thing to do) caused the same warnings to show up again.
The INTERRUPTVECTORS_INT0 mentioned above is this:
void InterruptVectors_Int0() interrupt 0 { if (IsRunning) { ZeroPassCount++; } }
IsRunning is defined in a much earlier file as
bit IsRunning = false;
(I might have forgotten a
volatile
here, but its presence does not have any effect on the problem) and ZeroPassCount is defined as
volatile unsigned int ZeroPassCount = 0;
in that same file. If I comment out just the
ZeroPassCount++;
, the program compiles fine (assuming the return statement from above still contains "BitIndex"), but commenting out the if-statement (i.e.
executes always) or having nothing commented out at all, causes the warnings to show up again.
In the "OVERLAY MAP OF MODULE: ..." section of the .MAP file there is indeed a link from INTERRUPTVECTORS_INT0/MAIN to ?PR?MAIN:
FUNCTION/MODULE BIT_GROUP DATA_GROUP XDATA_GROUP --> CALLED FUNCTION/MODULE START STOP START STOP START STOP =================================================================================== INTERRUPTVECTORS_INT0/MAIN ----- ----- ----- ----- ----- ----- +--> ?PR?MAIN MAIN ----- ----- ----- ----- ----- ----- +--> ?CO?MAIN ?CO?MAIN ----- ----- ----- ----- ----- ----- +--> ...
But I don't understand how this is possible, because InterruptVectors_Int0 does not call any functions. It merely updates a global variable.
Any insights into how I can systematically find out what's causing this and how I can fix it? Since some changes I made were completely unrelated to any of the warnings, any change I try might randomly make the problem disappear or reappear, so systematic trial and error is very difficult to do.
Indeed.
And there is the ongoing maintenance worry that you might change something in the code, but forget one of the details to keep the linker happy ...
It all makes sense when you know it. But getting from the symptom to the root cause is a mind-bending journey of "WTF?", "WHY?" and "HOW EVEN?".
But when everything is working smoothly, doing low-level programming is usually a lot of fun
you may not be familiar with the common standard non-maintainable code is worthless
I have, on occasion, when tasked with maintenance ended up rewriting the code to a maintainable shape