Grodriguez Grodriguez - 2 months ago 15
C Question

C compiler bug or program error?

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.


Answer

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 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).

Comments