0

I'm trying to come up with a portable way of preventing a function from being inlined. I found my solution in this old answer where there is a comment that 'it might not always work'.

void (*foo_ptr)() = foo;
foo_ptr();

My function is just incrementing a volatile, the purpose is to control the PC for validation (exercising some trace hardware), and I'm not concerned about the surrounding code - just that the flow will likely remain working when I come back to this in 10 years time (with new toolchains). I'd rather not use attributes or embedded assembler (I already need to support 3 toolchains, and I have something that appears to work now).

I am thinking that passing the address through a volatile will give me more protection. Is this necessary, or is there anything less ugly I can use?

Sean Houlihane
  • 1,698
  • 16
  • 22
  • Trying to be "portable" and "the purpose is to control the PC for validation" seems to contradict itself. I am not aware of a portable way to check the PC; this will always depend on a certain toolchain. And almost every toolchain has a way to prevent inlining (e.g. `__attribute__((__noinline__))` or so with gcc). – ensc May 25 '17 at 11:53
  • I have hardware monitoring the PC - I need to exercise that hardware (not test it). – Sean Houlihane May 25 '17 at 11:54
  • 1
    Put it in a separate file (compilation unit), compile that to object (or library) and link the resulting object to your "main" program. – wildplasser May 25 '17 at 11:54
  • define ``static const *FUN dummy = &your_function``. In order for the compiler to initialize this unused variable it will have to keep your function non-inlined as the inlined function do not have addresses. – alinsoar May 25 '17 at 12:41
  • @alinsoar I already do this, in order to configure the hardware unit with the trigger address. – Sean Houlihane May 25 '17 at 13:16

1 Answers1

3

The easiest way to totally avoid any chance of a function being 'inlined' is to place the function in a separate source file and bringing the function into the executable at link time rather than at compile time.

here is one way:

header_1.h #ifndef HEADER_1_H #define HEADER_1_H

void foo( void );

#endif // HEADER_1_H

source_1.c

...
void foo()
{
    // do something
}

source_2.c

#include "header_1.h"

int main( void )
{
    foo();
}

Then use the following compile/link statements

gcc -c ... source_1.c -o source_1.o
gcc -c ... source_2.c -o source_2.o
gcc source_1.o source_2.o -o source
user3629249
  • 16,402
  • 1
  • 16
  • 17