This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28386S: Linker does not perform function inlining

Part Number: TMS320F28386S

Tool/software:

Hello all,

Problem statement:

I am currently working on an application that, among others, features the following code structure:

// File interface.h
#pragma FUNC_ALWAYS_INLINE(some_function)
void some_function(uint16_t some_argument);

//File interface_implementation.c
#include "interface.h"

void some_function(uint16_t some_argument)
{
    // Some code that interacts with HW registers via pointers to volatiles
    // have also tried with code that does not access HW registers at all and also does not work
}

// File user_file.c
#include "interface.h"

#pragma INTERRUPT(user_isr)
static void user_isr(void)
{
    uint16_t argument = 10U;
    some_function(argument);
    
    // ISR flag handling etc..
}

My goal is to inline the some_function function call in the user_isr interrupt without having to use static inline on some_function . This way it is not needed to expose all internals of the some_function implementation. Given that the file user_file.c only sees the declaration of some_function but not its implementation I rely on the linker inlining the some_function function call. According to the document SPRU514Z Chapter 2.11 the linker should be capable of inlining functions. Please correct me if I am wrong on that and there are other ways to go around this.

By taking a look at the dissassembled output file it can be seen that an LCR instruction is used to call some_function thereby confirming that it did not get inlined.

Things that were tested (but did not solve the problem):

I've taken a look at the SPRU514Z document on how this can be done and I've come up with the following try (which in my case does not work):

  • CGT version: ti-cgt-c2000_20.2.1.LTS
  •  #pragma FUNC_ALWAYS_INLINE(some_function) right before the function declaration.
  • Compiler flags: --opt_level=4 --opt_for_speed=5
  • Linker flags: --opt_level=4 --opt_for_speed=5 (although I think it does not apply for the linker)

Additionally I've seen that in section 2.11.2 of SPRU514Z it is mentioned that inlining will not be done in a situation where it is "difficult" for the compiler to do so. Unless I missed something, I am not doing any of those. The "is not declared inline bulletpoint ..." is making me doubt although I tried explicitly using the inline keywork and it did not help.

I am for sure missing something but I do not see what it is. Could you please help me with this issue? In case you need further information I'll happily try to provide it.

Thanks a lot in advance for your help,

Best regards,

Francesc

  • Hello,

    I've brought this thread to the attention of the compiler experts who can best assist further.

    Thanks

    ki

  • Hello -- can you provide the full command line you are building with using teh tools?  Also, if you could provide a reproducible test case using preprocessed files, that would be helpful for us, please follow the directions in the article How to Submit a Compiler Test Case

  • Hello Alan,

    Here you find the flags I am using to compile and link:

    • Compiler: -v28 -ml -mt $\
      --float_support=fpu64 --idiv_support=idiv0 --tmu_support=tmu0 --fp_mode=relaxed $\
      --opt_level=4 --opt_for_speed=5 --printf_support=nofloat $\
      --symdebug:dwarf --symdebug:dwarf_version=4 $\
      --abi=eabi --gen_func_subsections=on $\
      --cla_support=cla2 --cla_signed_compare_workaround=on $\
      --advice:performance=all --relaxed_ansi $\
      --diag_suppress=10063 --diag_warning=225 --diag_wrap=off --display_error_number $\
      --check_misra="required" --misra_advisory=remark --misra_required=warning
    • Linker: --opt_level=4 --opt_for_speed=5 $\
      --diag_suppress=10063 --diag_warning=225 --diag_wrap=off --display_error_number $\
      --run_linker --warn_sections --heap_size=0 --stack_size=0x7F6 --entry_point=code_start --rom_model --zero_init=on

    Unfortunately I am not allowed to share the exact preprocessed files that I am using but I will try to create a reproducible test case in the following days and get back to you.

    Thanks a lot for your help,

    Best regards

    Francesc

  • Hello Alan,

    After trying to recreate a reproducible test case I found out what triggered the function to not get inlined.

    The initial code structure described in the first post is here extended with more details. The interface_implementation.c file (which implements the function to be inlined) also featured some non static functions that used __asm statements. Despite these functions not being called anywhere, when the entire project was compiled and linked the desired function was not inlined. Removing the __asm statements from the unused function caused "some_function" to get inlined as desired.

    //File interface_implementation.c
    #include "interface.h"
    
    void not_used_anywhere(void)
    {
        __asm(" EALLOW");
        
        // other things done with HW but no __asm statements
    }
    
    void some_function(uint16_t some_argument)
    {
        // Some code that interacts with HW registers via pointers to volatiles
        // have also tried with code that does not access HW registers at all and also does not work
    }

    Is it possible that a C file featuring __asm statements in non static functions causes all functions in that file to not be inlined by the linker anymore?

    According to SPRU514Z Chapter 2.11.2 a function will not get inlined if it contains __asm statements but I don't think this has anything to do with this behavior.

    On my side feel free to close this post, my problem has now been solved.

    Thanks a lot for your help,

    Best regards,
    Francesc

  • Before I close this thread, I want add a few comments that may be helpful to others who come across it later.

    For the compiler to inline a function, the call site and the full code for the function must both be visible at once.  A good way to implement this is described in this article (not from TI).  Note it requires you build for EABI and C99 by using the options --abi=eabi and --c99.  But that is almost always the case anyway.

    Thanks and regards,

    -George