Under what circumstances will C Linker eliminate unused volatile characters?

I use a very specific toolchain (SHARC DSP Processor from Analog Devices) and I would like to better understand my compiler / linker.

I have somewhere a mutable global variable:

volatile long foo; 

This variable is not used or mentioned in my code, but I want to save it in my final executable file (do not ask me why, the sad truth is sad).

I usually associate my project with the -e option. It tells the linker to remove dead code from the executable. Initially, I thought that no compiler would dare to remove any global variable, especially if these characters are declared mutable. Unfortunately this is the case.

Then I found the very specific pragma #pragma retain_name , which tells the linker that it saves the character, even if it is never used.

I would like to know if this situation can be found in some ISO / POSIX standards. I have always, although neither the compiler nor the linker made any assumptions regarding volatile characters. And thus, no compilers will ever try to remove a dead mutable variable or function from the final executable.

I am wrong?

+5
source share
2 answers

If one standard for C is the K & R book, little can be said about volatile , except that it is mentioned several times and is said to be related to optimization.

Appendix A.8.2 “Type specifiers” states the following:

Types can also be qualified to indicate the special properties of objects being declared. type specifier: Const volatile Type specifiers can be displayed with any type specifier. A const object can be initialized, but not assigned. For volatile objects, there is no implementation-dependent semantics. Comp. and volatile properties are new with ANSI standard. The purpose of const declares objects that can be placed in read-only memory, and possibly increase opportunities for optimization. The goal of volatile is to enforce implementation to suppress optimization that might otherwise occur. For example, for a machine with I / O memory mapping, a pointer to a device register can be declared as a pointer to volatile, to prevent the compiler from deleting apparently redundant links through a pointer. Except that it should diagnose explicit attempts to modify const objects, the compiler can ignore these qualifiers.

Focus on mine and pay attention to what the last paragraph says. This may mean that the compiler may in any case ignore the volatile qualifier.

Compilers will allow the volatile variable to remain unoptimized in my experience, even if they are never used. However, I'm not so sure about the linkers. The standard says very little about the layout process.

FWIW My general experience with commercial compilers for embedded purposes is that they sometimes do not fully comply with the standards. Recently, I have been using the TI compiler + linker toolchain and I can just say that it is really different from what I'm used to, with gcc + ld ports for ARM, for example ....

EDIT:

No, of course, K & R is not a standard. Let me take a look at a real standard, for example. the ISO C99 standard, obtained from here , in one paragraph in Section 6.7.3 Type qualifiers, 6 says:

An object that has a mutable type can be modified in ways that are unknown to the implementation or have other unknown side effects. Therefore, any expression that refers to such an object is evaluated strictly in accordance with the rules of an abstract machine, as described in 5.1.2.3. In addition, at each point in the sequence, the last value stored in the object agrees with what is prescribed by the abstract machine, except for cases unknown factors mentioned earlier. 114) What constitutes access to an object that has a type of volatile-qualified type defined by the implementation .

Unfortunately, I do not think this helps answer the question.

+2
source

You can create a dummy function with an external link that uses a variable.

 long help_us_keep_foo(void) { return foo; } 

If you do not analyze the entire program, this will prevent the removal of foo . If you are analyzing an entire program, you can use the trick as shown below.

 int main(int argc, char * * argv) { if (getenv("PRINT_THE_VALUE_OF_FOO_AT_PROGRAM_STARTUP")) printf("Your hovercraft is full of eels, and foo is %ld\n", foo); /* Do whatever your program has to do... */ return 0; } 

I use a similar trick (by inserting harmless print statements that check for an extremely unlikely condition) in the benchmarking code to make sure that the things I wanted to check are not optimized.

If the situation allows this, you can use a less “visible” trick, such as assigning foo = foo , but since it is volatile , I'm not sure if you can do it safely.

+4
source

Source: https://habr.com/ru/post/1212134/


All Articles