Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C compiler bug or program error?

Tags:

c

embedded

iar

I am using the IAR C compiler to build an application for an embedded micro (specifically a Renesas uPD78F0537). In this application I am using two nested for loops to initialize some data, as shown in the following MCVE:

#include <stdio.h>

#define NUM_OF_OBJS 254
#define MAX_OBJ_SIZE 4

unsigned char objs[NUM_OF_OBJS][MAX_OBJ_SIZE];
unsigned char srcData[NUM_OF_OBJS][MAX_OBJ_SIZE];

void main(void)
{
    srcData[161][2] = 10;

    int x, y;
    for (x = 0; x < NUM_OF_OBJS; x++)
    {
        for (y = 0; y < MAX_OBJ_SIZE; y++)
        {
            objs[x][y] = srcData[x][y];
        }
    }

    printf("%d\n", (int) objs[161][2]);
}

The output value is 0, not 10.

The compiler is generating the following code for the for loop:

     13              int x, y;
     14              for (x = 0; x < NUM_OF_OBJS; x++)
   \   0006   14....         MOVW      DE,#objs
   \   0009   16....         MOVW      HL,#srcData
     15              {
     16                  for (y = 0; y < MAX_OBJ_SIZE; y++)
   \   000C   A0F8           MOV       X,#248
     17                  {
     18                      objs[x][y] = srcData[x][y];
   \                     ??main_0:
   \   000E   87             MOV       A,[HL]
   \   000F   95             MOV       [DE],A
     19                  }
   \   0010   86             INCW      HL
   \   0011   84             INCW      DE
   \   0012   50             DEC       X
   \   0013   BDF9           BNZ       ??main_0
     20              }  

The above does not work: The compiler is apparently precalculating NUM_OF_OBJS x MAX_OBJ_SIZE = 1016 (0x3f8). This value is used as a counter, however it is being truncated to 8 bits (0xf8 == 248) and stored in 8-bit register 'X'. As a result, only the first 248 bytes of data are initialised, instead of the full 1016 bytes.

I can work around this, however my question is: Is this a compiler bug? Or am I overlooking something?


Update

  • This microcontroller has 7KB of RAM, and sizeof(int) == 2
  • Copying the data over using pointers (e.g. something along the lines of while (len-- > 0) *dst++ = *src++;) works fine.
like image 569
Grodriguez Avatar asked Sep 01 '16 09:09

Grodriguez


1 Answers

I am pretty much convinced that this is a compiler bug based on the following:

  • Copying the data over using pointers (e.g. something along the lines of while (len-- > 0) *dst++ = *src++;) works fine. Thus this does not look like a problem of RAM size, pointer size, etc.

  • More relevant perhaps: If I just replace one of the two constants (NUM_OF_OBJS or MAX_OBJ_SIZE) with a static variable (thus preventing the compiler from precalculating the total count) it works fine.

Unfortunately I contacted IAR (providing a link to this SO question) and this is their answer:

Sorry to read that you don't have a license/support-agreement (SUA). An examination such as needed for this case can take time, and we (post-sales-support) prioritize to put time and effort to users with valid SUA.

Along with some generic comments which are not particularly useful.

So I guess I'll just assume this is a bug and work around it in my code (there are many possible workarounds, including the two described above).

like image 200
Grodriguez Avatar answered Oct 03 '22 13:10

Grodriguez