Topic: Does Std discuss order of code generation for functions?
Author: spam.this@bogus.com (JT)
Date: Tue, 21 Jun 2005 15:25:02 GMT Raw View
We have some highly tweaked C++ code that uses embedded assembly. We
switched to a new compiler and the code no longer works. Not a
surprise. The code skips the return and branches to the next function.
This worked as long as the functions were adjacent in the generated
code. They are no longer adjacent with the new compiler, but I'm not
sure why, perhaps due to an optimization. The functions are still
adjacent in their declaration and definitions. I could not find
anything in the standard that discusses the order of generated code for
functions. We expect that this is implementation defined - is this the
case?
Thanks,
JT
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "msalters" <Michiel.Salters@logicacmg.com>
Date: Tue, 21 Jun 2005 12:38:41 CST Raw View
JT schreef:
> We have some highly tweaked C++ code that uses embedded assembly. We
> switched to a new compiler and the code no longer works. Not a
> surprise. The code skips the return and branches to the next function.
> This worked as long as the functions were adjacent in the generated
> code. They are no longer adjacent with the new compiler, but I'm not
> sure why, perhaps due to an optimization. The functions are still
> adjacent in their declaration and definitions. I could not find
> anything in the standard that discusses the order of generated code for
> functions. We expect that this is implementation defined - is this the
> case?
Of course. The entire notion of a contiguous address space is not
mandated by the standard. It may be segmented, and there is no need
for these segments to be ordered in any way. The order may also be
determined by execution order. An implementation may load functions
only when they're needed.
Furthermore, there is no reason for a single function to be contiguous.
A compiler may put the exception handling stuff in a separate segment,
only to be loaded if the exception actually happens.
Inlining too affects function order. A function that's used in a single
place can often be inlined, after which the original copy can be
eliminated.
If you're using embedded assembly, you're quite a long way from
portable code anyhow.
HTH,
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: llewelly.at@xmission.dot.com (Llewelly)
Date: Tue, 21 Jun 2005 18:07:48 GMT Raw View
spam.this@bogus.com (JT) writes:
> We have some highly tweaked C++ code that uses embedded assembly. We
> switched to a new compiler and the code no longer works. Not a
> surprise. The code skips the return and branches to the next function.
> This worked as long as the functions were adjacent in the generated
> code. They are no longer adjacent with the new compiler, but I'm not
> sure why, perhaps due to an optimization. The functions are still
> adjacent in their declaration and definitions. I could not find
> anything in the standard that discusses the order of generated code for
> functions. We expect that this is implementation defined - is this the
> case?
Yes. Standard C++ has nothing to say about this.
If you want to try emulating this in standard C++, implement the
second function as inline, and then call it conditionally from the
first. Then test the result carefully to ensure it still meets the
constraints (performance, stack space, code size, etc.) that
forced the original author to use that branch.
Another suggestion is to look at the generated assembly, to examine
the resulting object file, and experiment with compiler (and/or
assembler) options. You may find a combination of options that
does the trick.
The linker can also play a vital role in this. For example, it may be
that your second function is never otherwise used, and so your new
linker simply leaves it out of the final executable. Experiment
with linker options as well; modern linkers do not necessarily lay
out functions in the order they apper in the object files.
Note that some implementations provide detailed information about
layout of functions and so forth, but most provide little or no
such information.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: stephen.clamage@sun.com (Steve Clamage)
Date: Tue, 21 Jun 2005 18:21:05 GMT Raw View
JT wrote:
> We have some highly tweaked C++ code that uses embedded assembly. We
> switched to a new compiler and the code no longer works. Not a
> surprise. The code skips the return and branches to the next function.
> This worked as long as the functions were adjacent in the generated
> code. They are no longer adjacent with the new compiler, but I'm not
> sure why, perhaps due to an optimization. The functions are still
> adjacent in their declaration and definitions. I could not find
> anything in the standard that discusses the order of generated code for
> functions. We expect that this is implementation defined - is this the
> case?
I'll address a technical point not mentioned in other answers.
The topic is not implementation-defined. It is not addressed at all by the
standard. "Implementation defined" means the implementation must document how
the feature works.
This topic falls more under the category of "unspecified". The implementation
can do anything it wants as long as the program satisfies the "observable
behavior" requirements. The implementation does not have to document what it
does, and it need not be consistent.
---
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: swampmonster@der-ball-ist-rund.net (Paul Groke)
Date: Thu, 23 Jun 2005 15:03:48 GMT Raw View
===================================== MODERATOR'S COMMENT:
Let's try to keep this discussion closer to the charter, and not drift
away into coding techniques.
===================================== END OF MODERATOR'S COMMENT
Llewelly wrote:
> spam.this@bogus.com (JT) writes:
>
>
>>We have some highly tweaked C++ code that uses embedded assembly. We
>>switched to a new compiler and the code no longer works. Not a
>>surprise. The code skips the return and branches to the next function.
>>This worked as long as the functions were adjacent in the generated
>>code. They are no longer adjacent with the new compiler, but I'm not
>>sure why, perhaps due to an optimization. The functions are still
>>adjacent in their declaration and definitions. I could not find
>>anything in the standard that discusses the order of generated code for
>>functions. We expect that this is implementation defined - is this the
>>case?
>
>
> Yes. Standard C++ has nothing to say about this.
>
> If you want to try emulating this in standard C++, implement the
> second function as inline, and then call it conditionally from the
> first. Then test the result carefully to ensure it still meets the
> constraints (performance, stack space, code size, etc.) that
> forced the original author to use that branch.
Newer compilers might even generate code that performs equally well
without the second function being inline - at least some compilers
optimise "CALL+RET" to just a "JMP". And depending on the nature of
your code, the quality of the inline assembly code, the actual
hardware platform and the specific compiler used, the code generated
by a new compiler without most of the tweaks could even outperform
the code from the old compiler with tweaks. Especially when it comes
to tight loops and heavy if/switch usage. MSVC 7.1 for example can
generate very optimised code without any inline assembly and without
any or most tweaks by #pragmas or similar. And I believe that MSVC
is not the only modern C++ compiler that can generate lightning-fast
code.
Stack usage of course is another problem that might not be so
easy to solve.
If everything else fails you could try to compile the functions
with the (no longer working) tweaks in place, have the compiler
generate an assembler output, and correct the assembler code by
hand. Which of course would only be a suitable solution if that
code doesn't change often.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]