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.

Compiler/TM4C129CNCZAD: Const struct initialized with const pointer gets places in .data instead of .const

Part Number: TM4C129CNCZAD
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI C/C++ Compiler

Using compiler version 15.2.5 LTS, I'm trying to put a semaphore handle (which TI's headers define as a const pointer to an object) in a const structure to go into flash.  The compiler seems to do the wrong thing and place the entire struct in RAM if the initializing assignment is another const datatype.  The file is a C++ file.

typedef ti_sysbios_knl_Semaphore_Object* ti_sysbios_knl_Semaphore_Handle;

const ti_sysbios_knl_Semaphore_Handle my_sem = &some_semaphore;

struct mystruct {
  ti_sysbios_knl_Semaphore_Handle handle;
}

// is placed in .const
const mystruct x = {
  .handle = 0
}
 // should be placed in .const but is placed in .data
const mystruct y = {
  .handle = my_sem
}

  • my_sem is const, but it is not a constant expression (no kidding!) To get struct y into .const, you'll need to change it to say ".handle = &some_semaphore"
  • In C you'd be right, C++ does allow for const expression assignment though.  The problem is SYS-BIOS defines it as a const expression

    const ti_sysbios_knl_Semaphore_Handle my_sem = (ti_sysbios_knl_Semaphore_Handle)((ti_sysbios_knl_Semaphore_Handle)&ti_sysbios_knl_Semaphore_Object__table__V[2]);

    thus I cannot use it in the way you describe, I have to instead use the handle SYS-BIOS provides.

  • In response to this thread, I filed two entries in the SDOWP system.   One is a bug against the documentation.  The other requests an improvement in the compiler.

    Entry CODEGEN-2354 is a bug against the ARM compiler manual.  The manual states a variable marked const goes in the .const section (with a few rare exceptions.)  This is true for C.  But not C++.  In C++, the expression on the right side of the equals sign can be more than a simple constant or address.  When that occurs, the variable is not placed in the .const section.  For example ...

    Kaveh Vaghefi said:
    .handle = my_sem

    The expression my_sem is not an address, but a memory location.  It cannot be evaluated at build time.  Thus y is not placed in .const.  

    Entry CODEGEN-2355 does not report a bug, but requests an improvement.  In this case, if my_sem could be replaced by &some_semaphore, then y could be placed in .const.

    You are welcome to follow these entries with the SDOWP link below in my signature.

    Thanks and regards,

    -George

  • That's great, thanks for clearing this up and filing those entries.  I'm still curious as to the difference between address and memory location as you refer to them.  From the perspective of the compiler, I assume it treats an address as something fundamentally different from what you called a 'memory location'.  I'm assuming 'memory location' is just treated as a 32-bit integer and the compiler doesn't know it's actually and address so it doesn't treat it as such.  Is that right?

    It sounds like if CODEGEN-2355 is implemented, that it will do what is desired here.  Fundamentally, I'm trying to store statically created SYS-BIOS object references in flash instead of RAM (which seems like a reasonable thing to do in an embedded environment )

  • I'll explain by using an example that is simpler than yours, but is the same in the important aspects.

    const int *global_ptr = &variable;

    ... can be evaluated at build time.  Contrast that with ...

    const int *global_ptr = another_ptr;

    The expression another_ptr is not an address.  It is a memory location which must be read.  That can only occur at run time.  This is not supported in C.  But it is supported in C++.  

    Thanks and regards,

    -George

  • Ah.  To extend your example, if another_ptr is a const declared at compile time from an address, then why can't the compiler transitively connect the two?

    const int * const another_ptr = &variable;
    
    // can be evaluated at build time
    const int *global_ptr1 = &variable;
    
    // can't be evaluated at build time?
    const int *global_ptr2 = another_ptr;

    SYS-BIOS declares a `const ti_sysbios_knl_Semaphore_Handle` which is a typedef'ed pointer.  Why can't a const pointer be evaluated at compile time as an address?

  • Kaveh Vaghefi said:
    Why can't a const pointer be evaluated at compile time as an address?

    This is a compiler optimization.  I filed CODEGEN-2355 to request that the compiler implement it.

    Thanks and regards,

    -George

  • Awesome, thanks!