Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12606 Discussions

Compiler Bug: Wrong code generation

Altera_Forum
Honored Contributor II
1,401 Views

Hi there, 

 

Recently I've ported a program from NIOS I to NIOS II. When debugging the ported program I noticed a strange problem in the code generated. 

 

Basically, the compiler generated a wrong code for a nested switch statement. The problem arises if the code for the switch is bigger than a certain size. 

 

The C code that shows the problem is as follows: 

 

#include <stdio.h> void Func1() {    int j = 0;    for(int i=0; i<10; i++)       j += i; } void Func2() {    int j = 0;    for(int i=0; i<10; i++)       j -= i; } void Func3() {    int j = 0;    for(int i=0; i<10; i++)       j += 2 * i; } # define SOME_CODE()                                asm(".rept 71\n"                                    " nop\n"                                        ".endr\n") void BugSample(int var1, int var2) {# define HANDLE_CASE(__tag)                        case __tag:                                       printf(#__tag "\n");                           SOME_CODE();                                   printf(#__tag "\n");                           break;    switch(var1)    {       HANDLE_CASE(0)       HANDLE_CASE(1)       HANDLE_CASE(2)       HANDLE_CASE(3)       HANDLE_CASE(4)       HANDLE_CASE(5)       HANDLE_CASE(6)       HANDLE_CASE(7)       HANDLE_CASE(8)       HANDLE_CASE(9)       HANDLE_CASE(10)       HANDLE_CASE(11)       HANDLE_CASE(12)       HANDLE_CASE(13)       HANDLE_CASE(14)       HANDLE_CASE(15)       HANDLE_CASE(16)       HANDLE_CASE(17)       HANDLE_CASE(18)       HANDLE_CASE(19)       HANDLE_CASE(20)       HANDLE_CASE(21)       HANDLE_CASE(22)       HANDLE_CASE(23)       HANDLE_CASE(24)       HANDLE_CASE(25)       HANDLE_CASE(26)       HANDLE_CASE(27)       HANDLE_CASE(28)       HANDLE_CASE(29)       HANDLE_CASE(30)       HANDLE_CASE(31)       HANDLE_CASE(32)       HANDLE_CASE(33)       HANDLE_CASE(34)       HANDLE_CASE(35)       HANDLE_CASE(36)       HANDLE_CASE(37)       HANDLE_CASE(38)       HANDLE_CASE(39)       HANDLE_CASE(40)       HANDLE_CASE(41)       HANDLE_CASE(42)       HANDLE_CASE(43)       HANDLE_CASE(44)       HANDLE_CASE(45)       HANDLE_CASE(46)       HANDLE_CASE(47)       HANDLE_CASE(48)       HANDLE_CASE(49)       HANDLE_CASE(50)       HANDLE_CASE(51)       HANDLE_CASE(52)       HANDLE_CASE(53)       HANDLE_CASE(54)       HANDLE_CASE(55)       HANDLE_CASE(56)       HANDLE_CASE(57)       HANDLE_CASE(58)       HANDLE_CASE(59)       HANDLE_CASE(60)       HANDLE_CASE(61)       HANDLE_CASE(62)       HANDLE_CASE(63)       HANDLE_CASE(64)       HANDLE_CASE(65)       HANDLE_CASE(66)       HANDLE_CASE(67)       HANDLE_CASE(68)       HANDLE_CASE(69)       HANDLE_CASE(70)       HANDLE_CASE(71)       HANDLE_CASE(72)       HANDLE_CASE(73)       HANDLE_CASE(74)       HANDLE_CASE(75)       HANDLE_CASE(76)       HANDLE_CASE(77)       HANDLE_CASE(78)       HANDLE_CASE(79)       HANDLE_CASE(80)       HANDLE_CASE(81)       HANDLE_CASE(82)       HANDLE_CASE(83)       HANDLE_CASE(84)       HANDLE_CASE(85)       HANDLE_CASE(86)       HANDLE_CASE(87)       HANDLE_CASE(88)       HANDLE_CASE(89)       HANDLE_CASE(90)       HANDLE_CASE(91)       HANDLE_CASE(92)       HANDLE_CASE(93)       HANDLE_CASE(94)       HANDLE_CASE(95)       HANDLE_CASE(96)       HANDLE_CASE(97)       HANDLE_CASE(98)       HANDLE_CASE(99)       case 100:         {            Func1();            printf("Func1 called");            switch(var2)            {               case 2:               case 3:                 {                    Func2();                    printf("Func2 called");                    break;                 }               case 4:               case 5:                 {                    Func3();                    printf("Func3 called");                    break;                 }               default: break;            }            break;         }    } } 

 

In the above program we can see that the handling for the cases ranging from 0 to 99 simply call printf and insert a lot of NOPs. In the handling for the value 100, we have another switch and that is where the problem happens. If var2 equals 3 the function func3() gets called !!! 

 

I&#39;m compiling the program under Eclipse using the Release configuration. The compiler flags are: -DALT_RELEASE -O2 -g -Wall 

 

The version of GCC is 3.4.1 (Altera Nios II 5.1 b93) 

 

Note 1: The real program where I found the bug uses no inline assembly. 

Note 2: If I change to optimization level 1 (-O1) the code generated is correct. 

 

The disassembly of the function BugSample() for the case of wrong code generation (with comments added): 

 

010001e8 <_Z9BugSampleii>: 10001e8:    defffe04  addi    sp,sp,-8 10001ec:    00801904  movi    r2,100 10001f0:    dc000015  stw    r16,0(sp) 10001f4:    dfc00115  stw    ra,4(sp) 10001f8:    2821883a  mov    r16,r5 10001fc:    11000636  bltu    r2,r4,1000218 <_Z9BugSampleii+0x30> 1000200:    200490ba  slli    r2,r4,2 1000204:    00c04074  movhi    r3,257 1000208:    18caa704  addi    r3,r3,10908 100020c:    10c5883a  add    r2,r2,r3 1000210:    11000017  ldw    r4,0(r2) 1000214:    2000683a  jmp    r4 ;;; <Return>: ;;; 1000218:    dfc00117  ldw    ra,4(sp) 100021c:    dc000017  ldw    r16,0(sp) 1000220:    dec00204  addi    sp,sp,8 1000224:    f800283a  ret ;;; Handling of case 100: ;;; 1000228:    10001ac0  call    10001ac <_Z5Func1v> 100022c:    01004074  movhi    r4,257 1000230:    210a3704  addi    r4,r4,10460 1000234:    10082c40  call    10082c4 <printf> 1000238:    00c00084  movi    r3,2 100023c:    80fff616  blt    r16,r3,1000218 <_Z9BugSampleii+0x30> ;  -> goto <Return> 1000240:    008000c4  movi    r2,3 1000244:    8080030e  bge    r16,r2,1000254 <_Z9BugSampleii+0x6c> ; -> goto <label1>  (WRONG: should be bg, not bge) 1000248:    00404034  movhi    at,256 100024c:    0860a814  ori    at,at,33440 1000250:    0800683a  jmp    at            (address: 0x10082A0)   ; goto case 2/3 ;;; <label1>: 1000254:    00800144  movi    r2,5 1000258:    143fef16  blt    r2,r16,1000218 <_Z9BugSampleii+0x30> 100025c:    10001d40  call    10001d4 <_Z5Func3v> 1000260:    01004074  movhi    r4,257 1000264:    210a3b04  addi    r4,r4,10476 1000268:    02004074  movhi    r8,257 100026c:    4220b104  addi    r8,r8,-32060 1000270:    dfc00117  ldw    ra,4(sp) 1000274:    dc000017  ldw    r16,0(sp) 1000278:    dec00204  addi    sp,sp,8 100027c:    4000683a  jmp    r8 1000280:    01004074  movhi    r4,257 1000284:    210a3f04  addi    r4,r4,10492 1000288:    100837c0  call    100837c <puts> 100028c:    0001883a  nop 1000290:    0001883a  nop ... ;;; Code generated for: ;;; ;;; switch(var2) ;;;    case 2: ;;;    case 3: ;;;      { ;;;         Func2(); ;;;         printf("Func2 called"); ;;;         break; ;;;      } 10082a0:    10001c00  call    10001c0 <_Z5Func2v> 10082a4:    01004074  movhi    r4,257 10082a8:    210aa304  addi    r4,r4,10892 10082ac:    02004074  movhi    r8,257 10082b0:    4220b104  addi    r8,r8,-32060 10082b4:    dfc00117  ldw    ra,4(sp) 10082b8:    dc000017  ldw    r16,0(sp) 10082bc:    dec00204  addi    sp,sp,8 10082c0:    4000683a  jmp    r8 

 

As a workaround, I&#39;ll use optmization level 1 to generate my real program.  

 

Anyway, I believe that this subject deserves some investigation. 

 

Regards, 

 

mrwar
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
332 Views

No one any comment on this? It seems to be importand enough to know if it&#39;s a mistake from mrwar, or a real bug!

0 Kudos
Altera_Forum
Honored Contributor II
332 Views

 

--- Quote Start ---  

originally posted by svhb@Sep 21 2006, 04:11 PM 

no one any comment on this? it seems to be importand enough to know if it&#39;s a mistake from mrwar, or a real bug! 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=18394) 

--- quote end ---  

 

--- Quote End ---  

 

Yes, I can reproduce this on our NIOS2 board using the nios2-elf-g++ version 3.4.1 under Linux. 

 

I&#39;ve crosschecked this with a i686-pc-linux-gnu-g++ 3.4.1. With this one, the generated code runs correctly and also a fast search in the gcc bugzilla didn&#39;t come up with a matching bugreport, so it seems like this is a nios2-port specific bug. 

 

@mrwar: Did you already forward this to Altera support? 

 

Regards, 

Andreas
0 Kudos
Altera_Forum
Honored Contributor II
332 Views

Thanks Andreas for confirming the bug. 

 

It seems that the bug is related to the size of a relative jump, which I believe is handled in a platform dependent way in GCC. 

 

Today, I sent a bug report to Altera. When I get any answers, I&#39;ll send to the Forum. 

 

Regards, 

 

mrwar
0 Kudos
Altera_Forum
Honored Contributor II
332 Views

Should some Altera-NIOSII people not keep an eye on the forum??

0 Kudos
Reply