Tool/software: TI C/C++ Compiler
I can't seem to figure if I can get the TI linker (MSP430 toolchain) to alias function sections. This results in massive output bloat when using templatized code. Consider the following trivial example:
#include <msp430.h> #include <stdint.h> template <typename T> const T& min(const T& a, const T& b) { return a < b ? a : b; } volatile uint16_t x = 1, y = 2, z; volatile void* p1 = (void*)0xbeef; volatile void* p2 = (void*)0xbeef; volatile void* p; /** * main.c */ int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer z = min(x, y); p = min(p1, p2); return 0; }
Here, the two min functions are byte-by-byte identical, since comparing pointers is exactly the same as comparing unsigned integers of the same size.
Compiling the above and checking the output with nm(1) yields:
0000c25c T _Z3minIPVvERKT_S4_S4_
0000c266 T _Z3minIVjERKT_S3_S3_
Clearly one of these function sections can be discarded and the other aliased to it. Yeah, it would make it difficult to debug, but for release builds I don't care about this and just want to fit it into a smaller and cheaper processor. I don't care if debugging or even profiling requires a 16k flash device, as long as all this goes away for release builds.
It's pretty easy to verify with an interleaved C source listing that the two functions do in fact emit exactly the same code.
And, while this is a trivial example that would probably go away at higher levels of optimization due to opportunistic inlining.
I've tried disabling all debug information, as you can see from the asm listing below, but it still won't combine sections.
.sect ".text:_Z3minIVjERKT_S3_S3_" .clink .global _Z3minIVjERKT_S3_S3_ ;***************************************************************************** ;* FUNCTION NAME: const T1 & min<volatile unsigned int>(const T1 &, const T1 &)* ;* * ;* Regs Modified : SP,SR,r12 * ;* Regs Used : SP,SR,r12,r13 * ;* Local Frame Size : 0 Args + 0 Auto + 0 Save = 0 byte * ;***************************************************************************** _Z3minIVjERKT_S3_S3_: ;* --------------------------------------------------------------------------* ;---------------------------------------------------------------------- ; 5 | const T& min(const T& a, const T& b) { ;---------------------------------------------------------------------- ;---------------------------------------------------------------------- ; 6 | return a < b ? a : b; ;---------------------------------------------------------------------- CMP.W @r13,0(r12) ; [] |6| JLO $C$L1 ; [] |6| ; [] |6| ;* --------------------------------------------------------------------------* MOV.W r13,r12 ; [] |6| ;* --------------------------------------------------------------------------* $C$L1: RET ; [] ; [] .sect ".text:_Z3minIPVvERKT_S4_S4_" .clink .global _Z3minIPVvERKT_S4_S4_ ;***************************************************************************** ;* FUNCTION NAME: const T1 & min<volatile void *>(const T1 &, const T1 &) * ;* * ;* Regs Modified : SP,SR,r12 * ;* Regs Used : SP,SR,r12,r13 * ;* Local Frame Size : 0 Args + 0 Auto + 0 Save = 0 byte * ;***************************************************************************** _Z3minIPVvERKT_S4_S4_: ;* --------------------------------------------------------------------------* ;---------------------------------------------------------------------- ; 5 | const T& min(const T& a, const T& b) { ;---------------------------------------------------------------------- ;---------------------------------------------------------------------- ; 6 | return a < b ? a : b; ;---------------------------------------------------------------------- CMP.W @r13,0(r12) ; [] |6| JLO $C$L2 ; [] |6| ; [] |6| ;* --------------------------------------------------------------------------* MOV.W r13,r12 ; [] |6| ;* --------------------------------------------------------------------------* $C$L2: RET ; [] ; []
Again, for things like non-trivial templatized base classes the bloat is absolutely massive, making the toolchain practically unusable.