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.

TI c6x compiler struct initialization policy

Hi All!

I'm trying to figure out the way the TI compiler initializes a C structure.

I found this thread e2e.ti.com/.../442988 and understood that static and global structures are not zeroed by the compiler to avoid time wasting on zeroing a memory which is already prepared (this is assumed) by the linker.

However the policy applied to structures allocated on the stack (automatic objects) is unclear for me. The official note on processors.wiki.ti.com/.../C89_Support_in_TI_Compilers has no word on it (only static objects mentioned).

I tried 2 versions of the TI C6000 compiler and found a different behaviour related to automatic struct timespec:

    struct timespec
    {
        time_t tv_sec;        /* Seconds.  */
        long_t tv_nsec;    /* Nanoseconds.  */
    };

    struct timespec ts = {.tv_sec = 1};

- on TI c6x compiler version 7.4.8 I've got the second field of this structure (ts.tv_nsec) initialized with zero (I tried to obtain garbage there different ways but had no luck)

- on TI c6x compiler version 7.4.15 I've got the second field initialized with random garbage

- on both versions I've got both fields zeroed, when I used declaration struct timespec ts = {0};

- on both versions I've got the second field initialized with random garbage, when I used GCC-like declaration struct timespec ts = {};

Could you please pour some light on a situation? Should I manually zero all fields of the automatic structures, is it somehow version-specific and what will be the final policy declared by TI?
Thank you!

  • The thread you reference states that the behavior of not zero-initializing is a COFF-only behavior. Under EABI, the compiler behaves as the C standard requires (uninitialized globals are initialized to zero).

    For your testing, are you using --abi=eabi?
  • Thank you for fast reply!

    Yes, I use the COFF-mode (seems there is no support for EABI on DSP/BIOS 5.42 e2e.ti.com/.../352660) and understand the "specifics" related to global/static variables initialization.

    The question widens range to cover the automatic (local) objects. These objects should not be affected by assumed linker or bootloader behaviour (zeroing memory) and binary file format.
  • Alexander Razinkov said:
    the policy applied to structures allocated on the stack (automatic objects) is unclear for me

    They are not initialized.  Please see this article (not from TI) for more detail.

    Thanks and regards,

    -George

  • Thank you for reply!

    I found this statement from the source you provided:
    "When an automatic array or structure has a partial initializer, the remainder is initialized to 0, just as for statics."

    So, should I expect the partialy initialized automatic struct to be zeroed (like in TI c6x v.7.4.8) or not zeroed (probably following the logic "we don't zero the statics, so the remainders of the automatic struct should conform the common rule and contain garbage like statics do in that case", v.7.4.15)?
  • Again, you need to keep in mind that the TI COFF ABI does not strictly follow the C standard. The C standard says that for all static scope variables (globals or static locals), all uninitialized elements are by default initialized to zero; it also says that for any local(auto) variables with an initializer which doesn't initialize all of the elements, all uninitialized elements are initialized as if it were a static scope variable (by default initialized to zero). EABI follows these semantics.

    For TI COFF ABI, on the other hand, elements that are not explicitly initialized are not initialized at all, and could be garbage.

    You are using what is called a "designated initializer" to initialize an element by name; this is expected to work.

    You may be running afoul of known defect SDSCM00046439, which was fixed in C6000 compiler version 8.0.0; please try this version to see if it fixes the problem.
  • I just re-read the thead. You are using COFF, and you are not explicitly initializing the second element. This element will not be initialized, and will be garbage. This garbage could just so happen to be 0, and that is not uncommon, but it's still garbage. If you need it to be zero, explicitly initialize it, or take care to zero-initialize the .bss section at startup or load time.
  • Archaeologist, George, thank you very much for your patience!

    This issue is very important for us because it could lead to a significant refactoring for our project: automatic structure partial initialization is a widely used pattern, you see..

    I see the strict logic through your explanation regarding the C standard policy:

     Archaeologist wrote:The C standard says that for all static scope variables (globals or static locals), all uninitialized elements are by default initialized to zero; it also says that for any local(auto) variables with an initializer which doesn't initialize all of the elements, all uninitialized elements are initialized as if it were a static scope variable (by default initialized to zero). EABI follows these semantics.


    That's exactly what I expected when I first met the known issue with global/static objects initialization (our project was originaly developed using GCC and a lot of "magic" bugs followed). We fixed static/globals, that's clear here. But on the TI c6x compiler v7.4.8 I found no way to obtain garbage on partialy initialized automatic (local) structures declared like (exact types are irrelevant, of course):

    struct timespec ts = {.tv_sec = 1};

    and

    struct timespec ts = {0};

    I even tried to fill the memory with garbage using the bootloader before loading the DSP/BIOS: it seemed like the compiler explicitly initialized the remainder of the structure to zero in all cases. These structures are allocated on the volatile stack - it's too suspicious to always have zeroes on the right places by a pure luck.

    So, was it a "pure luck" which evaporated with v.7.4.15, or is it just a temporary deviation of the policy?

    Are the initialization of automatic structures like:

     struct timespec ts = {0};

    also unsafe and their current conformance to C Standard is just a luck?

    Thank you in advance for your help!

  • I looked at the assembly code generated for this source code by 7.4.8:

    #include <time.h>
    typedef long long_t;
    struct timespec
    {
        time_t tv_sec;        /* Seconds.  */
        long_t tv_nsec;    /* Nanoseconds.  */
    };
    struct timespec foo()
    {
        struct timespec ts = {.tv_sec = 1};
        return ts;
    }
    

    The compiler emits the initializer value in the .const section and copies it to the local variable every time the function is entered.  It just so happens that in 7.4.8, the compiler emits an initializer into .const that is the same size as struct timespec, and the uninitialized fields are filled with zero.  When this initializer value is copied over the local, the field will be initialized to zero.  

    This will happen consistently for 7.4.8, but there's no guarantee that version of the compiler won't perform the initialization differently with different command-line options.  Different versions of the compiler may (without notice!) also choose to perform the initialization differently, and you might end up with a value copied from an arbitrary location that won't be zero.  (By the way, 7.4.15 produces the same code as 7.4.8; I could not reproduce your results exactly.)  

    For COFF ABI, the compiler does not guarantee anything about uninitialized elements in this case.  It just so happens, as an unintended result of the way the compiler chose to do the initialization, that it is being initialized to zero.  If you need to guarantee a particular value, you must initialize it yourself, or switch to EABI.

  • Thank you very much!
    Now it's clear, and it's a sad news for us, because EABI is not an option for DSP/BIOS, unfortunately..

    This aspect seems to be COFF-specific and compiler-independent: other TI DSPs are also should be checked, right?
  • I know that more recent versions of DSP/BIOS do support EABI.  Since it sounds like you would benefit from C conforming behavior, I think you should explore this possibility.

    Yes, it's very COFF-specific, and yes it's unspecified behavior, so a given TI COFF compiler might do unpredictable things.   However, we definitely do not plan to investigate this issue for other TI COFF compilers because, being unspecified, there is no guarantee whatsoever that the compiler will do a particular thing.  If using COFF and the user needs to know what the element is initialized to, the user must provide an explicit initializer for that element.