How to stop optimizer discard unused variables?
Asked Answered
H

2

7

I would like to debug my code and can't access the internal layer in the process since this would disturb the communication with the hardware. (volatile operations are performed where the watchlist would interfere with the basic read accesses.)

So I'm testing the interface's return values but the IAR compiler does even optimize unused volatile variables away.

and a statement like this:

i = object.foo();
if (i)i=i;

doesn't help either.

I found here on SO just answers that advice for that case to use i/o operations. but that's no option either, since I don't have the option of including the C standard libraries. and the project itself doesn't need i/o there is no own variant of input/output functions.

So what are my options except disabling the optimizer?

Hostetler answered 16/9, 2015 at 11:50 Comment(13)
What do you mean with "unused volatile variables away"?Gang
When debugging, the proper solution is actually to disable the optimizer. Avoid debugging optimized code unless you are a masochist.Headpiece
@Olaf: Don't understand your question? that they get trimmed anyway. I thought volatile would prevent this but I missunderstood the scheme.Hostetler
@Headpiece your probably right with that, and my conclusion is that that would be indeed the cleanest and most efective way. you should add that to your answer as it even increases your posts quality ;)Hostetler
It's legal to optimize out unused volatile variables. Writing and reading them is observable behavior and may not be optimized out, but then they're obviously no longer unused.Literati
You specifically asked how to do it without disabling the optimizer.Headpiece
@MSalters: I'm not saying thats wrong. I was just not aware of when I posted the code.Hostetler
@Lundin: true story, but anyway I would thing it should be noted after my personal impression growth i walked thorugh the last 2 hours. But what ever you do. your answer is satisfing.Hostetler
@Zaibis: It is not clear to me. You do not read nor write the variables, nor are they hardware-registers (I presume the latter), so why is it a problem anyway they get optimized-out? The only point left would be DMA buffers, but even these would have to be allocated and accessible from your code (at least to write their address to the DMA).Gang
Have you tried #pragma required=symbol? It should not work with local variables, but should keep any statically linked variable or function.Bolide
@Olaf the point is, because I'm debugging. and in case I'm debugging It would be nice to have the variable exist when I'm watching it.Hostetler
@Olaf: And if you are arguing I could simply watch the variables where the calculations come from, thant thats what I tryed to describe in the OP: I can't watch them, because they are configured to be overwritten by next value after beeing read. and the IAR watchlist it self woudl be triggering the "registry was read" event, so the programm flow which in generall is ensured would become desynced and the programm wouldn't work probably anymore. so I need to check them some where else. and as thats not so easy my approach was, its best just declarign some variables for debug purposes.Hostetler
@Zaibis: Hmm.. I did something similar with gcc and had no problems. However, it is often necessary anyway to do destructive debugging: set watch/breakpoints wisely, run and once triggered inspect the state, then reset and start over. Some modern MCUs (e.g. STM32) allow to stop certain clocks if the CPU is halted, btw. An alternative is to use trace features (some allow to include a custom data stream, including timestamps) or the classical serial link (which might as well be SPI).Gang
H
5

The most reliable way is to find a setting in your linker files that forces a certain variable to get linked. But that's of course completely system-dependent.

Otherwise, the portable standard solution is simply to write (void)i; somewhere in the code. That works for most compilers. If it doesn't, you can take it one step further:

#ifdef DEBUG_BUILD
volatile int dummy;

// all variables you would like to have linked:
dummy = i; 
dummy = j;
...
#endif

Or if you are fond of obscure macros:

#define FORCE_LINKING(x) { void* volatile dummy = &x; }

(void* since that is type generic and works for every kind of variable. * volatile to make the pointer itself volatile, meaning the compiler is forbidden to optimize away the write to it.)

Headpiece answered 16/9, 2015 at 12:47 Comment(1)
I think const void or auto should be more generic.Patriotism
A
5

A common way is to put it into a while loop via a macro.

#define KEEP_UNUSED(var) do { (void)var; } while(false);

IAR also has an extension called __root: http://supp.iar.com/FilesPublic/UPDINFO/004350/manuals.htm

The __root attribute can be used on either a function or a variable to ensure that, when the module containing the function or variable is linked, the function or variable is also included, whether or not it is referenced by the rest of the program.

Abercrombie answered 16/9, 2015 at 11:53 Comment(6)
I was thinking of a loop aswell but that looked to me like an awfull work. but the macro idea didn't came into my mind. should be doing it. I'll let you know.Hostetler
the gcc edit I was aware of, but I'm using IAR's commercial compiler for embedded systems. (which one might assume should be aware of such cases and at least respect volatiles for that reason...)Hostetler
By the way, I assume you meant var isntead of expr, don't you?Hostetler
And nope, even after beeing used in a false loop the compiler is able to cross it out. So sadly this isn't solving my problem.Hostetler
I fixed the expr thing. And I missed you use IAR. IAR has a special extension called __root. See supp.iar.com/FilesPublic/UPDINFO/004350/manuals.htm Does that work?Abercrombie
definitely the right answer! gcc will keep optimise out unused vars no matter what I triedFranni
H
5

The most reliable way is to find a setting in your linker files that forces a certain variable to get linked. But that's of course completely system-dependent.

Otherwise, the portable standard solution is simply to write (void)i; somewhere in the code. That works for most compilers. If it doesn't, you can take it one step further:

#ifdef DEBUG_BUILD
volatile int dummy;

// all variables you would like to have linked:
dummy = i; 
dummy = j;
...
#endif

Or if you are fond of obscure macros:

#define FORCE_LINKING(x) { void* volatile dummy = &x; }

(void* since that is type generic and works for every kind of variable. * volatile to make the pointer itself volatile, meaning the compiler is forbidden to optimize away the write to it.)

Headpiece answered 16/9, 2015 at 12:47 Comment(1)
I think const void or auto should be more generic.Patriotism

© 2022 - 2024 — McMap. All rights reserved.