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
while (len-- > 0) *dst++ = *src++;) works fine.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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With