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 bug: Initialization constant expression not honoured

Other Parts Discussed in Thread: TMS320F28035

If we have a structure or an array with a 32 bit member and when the structure / array is initialized with a constant expression, it is ignored and the element is initialized to zero instead.

How can this happen? What happened to the parsed expression tokens? This is a nasty bug.

struct  {

 int32 x;

int32 y;

}  z;

struct z my = { 128 * 1024, 0x20000};

int32 myarr[] = { 128 *1024, 0x20000};

The first elements only get initialized to zero and the second element gets the right value.

Please fix the same.

Thanks

Sayee

  • Sayee,

    Do you have another compiler that works the way you expected this to work? For that matter, does the TI compiler build this without errors?

    Which device architecture are you using? Which compiler version, and which version of CCS?

    Mokan Kanna said:

    struct  {

     int32 x;

    int32 y;

    }  z;

    This does not generate a type that can be used to define other variables, but allocates a struct named z with the two int32 members. You have two choices of how to allocate and initialize a struct of this type construction:

    Alternative 1: init to z said:

    struct  {

     int32 x;

    int32 y;

    }  z = { 128 * 1024, 0x20000};

    Alternative 2:typedef said:

    typedef struct  {

     int32 x;

    int32 y;

    }  zStruct;

    zStruct my = { 128 * 1024, 0x20000};

    Both of these work fine with the C64x+ simulator in CCSv4.2, compiler 7.0.4.

    And the array worked fine without changes.

    Regards,
    RandyP

     

    If you need more help, please reply back. If this answers the question, please click  Verify Answer  , below.

     

  • Hello Randy

    The versions are:

    CCS 3.3.83.19

    CGT 5.2.9

    The target processor is TMS320F28035

    The code was typed direct on the mail and as I see, it has bug. But you can typedef a struct or create an array and try initializing elements with a constant expression and see if the elements get properly initiailzed! That is the CRUX OF THE REPORTED BUG.

    It compiles without errors. But the first elements (of constant expression) have been initialized to zero instead of the evaluated value in both structure as well array definitions.

    Sayee

  • Mokan Kanna said:

    struct z my = { 128 * 1024, 0x20000};

    This test case has signed integer overflow, which is undefined behavior, and thus the code is not legal [On C2000].

    On C2000, "int" is only 16 bits.  The two operands of the multiplication are unsuffixed decimal constants which fit in "int", so both are considered "int".  The result of a multiplication of two "int" is still "int", and "int" cannot hold the result of that multiplication (131072, which is 0x20000 in hex).  The compiler is truncating to the last 16 bits, which just happen to be zero.

    To fix this, give one or both of the operands of the multiply the "long int" suffix:

    struct z my = { 128L * 1024L, 0x20000};

    See also : http://www.ti.com/litv/pdf/spra683 "How to Write Multiplies Correctly in C Code"

    When I run the C2000 compiler with no options, I get the following warning, which is exactly what's wrong here.  What options are you using?

    warning: integer operation result is out of range

  • Hello Archaelogist,

    Thanks for explanation. Yes. I can take it as an answer. Is there any ANSI directive for this? But please consider the shotcomings / drawbacks as explained below:

    This constant expression evaluation is only at compile time and I guess it should be done at the same precision as the datatype of the target  (or higher, typically 32bit - the processor type) which is straight forward and not to be decided by the members of the constant expression involved. For example, if the same initializing is carried out by expression "1 << 17" it will be honoured correctly, I guess. No decisions on 1 (or for that matter 17). If such decision is driven by the member values of the expression, then the type of binary operator (for example, << Vs *) will also have to be factored to decide the size of final result.

    But here, I would like to quote my experience with one other company's 8 bit assembler. Though, it is just 8 bit, all constant expression evaluation at assemble time are done only in 32 bit precision and finally cast to the target datatype. This is well documented too! 

    C2000's being 32 bit controllers, is it not natural to expect the expression evaluations at compile time done in 32 bit? Some introspection needed here.

    Thanks again.

    Sayee

  • The TI compiler evaluates this particular expression exactly as the C standard requires.  The C standard requires that arithmetic be carried out in a type dictated by the types of the operands.  The compiler is not allowed to perform an "int" computation with type "long".  This is described in the C standard section "Usual arithmetic conversions", ISO C89 6.2.1.5 and C99 6.3.1.8.

    The expression 1<<17 is not legal for C2000, because it also causes signed integer overflow.  You need to use "1L<<17".

    The rules for expression evaluation in assembly code are completely separate from C code.  An assembler vendor is perfectly free to define expression evaluation in the assembler to be done in whatever precision they like, but if the compiler doesn't follow the standard, it's not a conforming C compiler.

    The "natural" data type of the C2000 is 16 bits, not 32, and this is the reason "int" is 16 bits.