Topic : Switch Case Compiler Bug

Forum : ST7/STM8

Original Post
Post Information Post
August 7, 2011 - 7:56pm
Guest

I believe I have found a bug in the Raisonance compiler when switching on unsigned 32 bit numbers. I have a value defined using a #define in an included header file that is compared to a value received from a CAN (controller area network) data frame. I first noticed that I could send a message with the correct data and the correct code path was not executed. I began debugging and followed the issue down the disassembly and it appears that it is comparing bits 31 – 16 and 7 – 0, but not bits 15 – 8. Please see link below for a screen grab of the debug session. On the right side I have the disassembly open and in side the red box and I expected to see two LWD/CPW calls. Instead I see it loading 16 bits from address 0x6b (see red box in Memory #1) and the next load is a LD instruction that only loads / compares address 0x6E. If I am in fact looking at this correctly, why is address 0x6d (value 0xEE) not loaded and compared while in the switch statement? I have seen this problem several times, but never dove this deep to see what it was doing. There might be something I am missing here, so if there is any other information / tests you would like me to run please let me know. I can also provide a MAP file if would be helpful, but it's rather large and did not want to post it until it was requested. On a side note, I have tried the latest compiler and out of the box it would not compile the existing code that builds and runs with my current compiler. If the fix is to upgrade to the latest compiler I will have to find out if I can transfer my full license. System Information OS: Windows 7 Pro 64 bit IDE: ST Visual Develop Compiler: RCSTM8 COMPILER V2.26.09.317 Linker: LINKER/LOCATOR RLST7 V2.26.09.317 OMf2ELF: OMF2ELF 0.07.10 Target: STM8A51A9

Replies
Post Information Post
+1
0
-1
August 8, 2011 - 11:26am
Raisonance Support Team

Hi,

Bad luck for you, it's the only week in the year during which all our STM8 compiler gurus are on vacation. I'll try to help but you might have to wait until nex Monday...

I made a few tries and I saw no problem. It might be in relation to something specific to your project. (compile options, values of the cases, etc.) And of course it could have been fixed, considering your compiler is about two years old...

For understanding the issue I will need an example project that shows the problem. (a complete project that I can recompile, including source files, header files, etc.) Please send it to "support@raisonance.com", and include a link to this forum thread in the text of the email.

Best Regards,

Vincent

+1
0
-1
August 8, 2011 - 9:44pm
Guest

Thanks for the reply. I stripped down the large project to try and give you the smallest code base that creates the error. However after stripping it down, my statement about the #defines not working as a case does not hold up. It works as expected, and the ASM looks like I would have expected.

So the question becomes, is there something that might cause a switch to be compiled incorrectly? I saw in the release notes, that in a previous version that optimizing the compiler for speed caused the switch statements to produce incorrect code.

Note that I am still working on creating a project for you that shows the behavior that I am seeing.

+1
0
-1
August 9, 2011 - 10:08am
Raisonance Support Team

Hi,

There have been many corrections in the compiler since the version that you are using, several of them could impact the switch, and some of them are known to impact it. To tell you more I would need to have a project that shows the problem.

The generation of the code for a switch/case statement is a very complex thing. You should expect that any change to the function, even minor and even outside the switch statement, can lead to a different asm code. Changes to the other functions or other files should not affect it.

If you have a spare PC you could try and install the latest version of the compiler, which will work in full mode for seven days. That should allow you to see if the corrections I spoke about above correct your problem.

I hope it helps.

Best Regards,

Vincent

+1
0
-1
August 9, 2011 - 2:28pm
Guest

I will set up a spare machine today and give the new compiler a shot. I would also like to clarify, I never meant to give the impression that I could guess the asm output for an entire switch statement. To determine right and wrong, my criteria was 'does it make sense?'. For instance, when switching on a uint32, I would expect to see the comparison of two 32 bit numbers (2x LDW and 2x CPW).

+1
0
-1
August 9, 2011 - 3:05pm
Raisonance Support Team

Hi,

Yes I agree that seeing your report, there is (or was) probably a bug there. Sorry if I was not clear. My points were...

1. The bug might have been corrected some time ago.

2. Even if it is still present, we need a test case here for correcting it.

3. For making the test case by reducing your complete application, you must make sure that you do not modify the function that contains the switch. (and also the type declarations, variable declarations, defines, etc. that the function uses) Any modification to this function, even minor, can lead the compiler to generate a completely different code, which might hide the bug. You can remove the comments for obfuscating, and eventually rename some items, provided you rename them in all the places where they are referenced.

Best Regards,

Vincent

+1
0
-1
August 9, 2011 - 6:32pm
Guest

Alright, I have downloaded the latest compiler and Ride 7. The project builds with zero errors and warnings (excluding some warnings about unused variables from debug code). This is further than I got last time I tried the new compiler, however it now appears that the target never leaves initialization mode.

It starts a the HW reset vector (0x6000), then I can single step the ASM and it ends up getting hung somewhere in ZeroData. For example: I enter debug mode and it run. The target does not appear to do anything so I press Stop Program. Each time i hit Stop Program, it stops on a ZeroData entry in the ASM : "0x9e38 <?C?ZeroData+9>"

Any ideas?

+1
0
-1
August 9, 2011 - 8:35pm
Guest

Another update. I have since fixed the issue with not getting past initialization. My application is bootloadable, so I have had to modify the startup.asm file. Apparently this file has changed in the past two years. When using the default file the compiler loads in, it works fine.

However, the issue with the switch statement still persists. The ASM does look substantially different, but the outcome is the same. I will try again to build a project that shows this behavior. I really hope these posts help someone else too, because this has been a nightmare to deal with!

+1
0
-1
August 12, 2011 - 5:42pm
Guest

Update: After running a few more tests, I found a few more data points that I would like to share. Test 1: Using the same code base that causes issues as shown on my first post, I started with a simple switch statement and began increasing the complexity (adding points, different casts, etc...) all of which worked as expected. In other words, I was unable to create the switch bug in main using similar complexities as seen in the buggy portion. Test 2: Just to see if I could the section of code to execute, I added an if/else if block that decoded the #define values into an enumeration and switched off of those. This test worked as expected, meaning all code paths were executed properly. Here is a screen grab of the debug session showing the dis-assembly / memory during this test.

Test 3: I tried the problematic code with the latest compiler and it still failed. I below I have the screen grab of the debug session showing the dis-assembly and break points. Latest Compiler Failure At this point in time I am 100% stumped and really hope you guys can enlighten me. Thanks!

+1
0
-1
August 16, 2011 - 11:22am
Raisonance Support Team

Hi,

Thanks for your patience. We understand how frustrating this experience may have been for you, and we will do our best to fix the problem out.

Here are few things to try:

- Your problem may be related to the optimizer (part of our compiler). One thing to experiment is to lower the optimization level down, and check whether this fixes the problem.

- In your first message you mention that you perform a switch on 32-bit values. You don't *really* expect the values to be 32-bit, do you? The C language can handle any integral type expressions in switch statements, however handling 32-bit values is unnecessary complex on RCSTM8. You may have to rework your code a bit so that the switch only handles 16-bit values.

If everything fails, can you send a zipped copy of your faililng project to (VincentC is out of the office) so that we can reproduce and analyze the problem?

Best Regards,

+1
0
-1
August 16, 2011 - 4:33pm
Guest

Regarding your three comments

1) For all of my projects I use the Normal / No optimizations. I did however try both the Speed and Size optimizations out of desperation. All of them demonstrated the same issues.

2) I switching on CAN SAE J1939 Parameter Group Numbers (PGN) which are 18 bits long. So no I really don't need 32 bits, but I do need 18. For some additional background information, in the reported failures the switch statement evaluated value 0xEE00 as 0xEA00. Meaning the 0xEE00 messages were always dropping into the 0xEA00 case. The interesting point I would like to make here is that in my quest to generate a small program that creates this error, I tried a mixed range of values (all cast as u32) ranging from 65000 to 67000, to make sure the values did cross the 16 bit boundary, worked as written.

While I have seen these issues in my own code base (I changed them out with if / else if), the current issue is in a purchased library. We really would not like to have to modify and maintain an external library because of compiler issues(not saying it is a compiler bug, but at least an issue with my code base coupled the the compiler)

3) Per our client's wishes, we are unable to send you the whole project. If I am continually unsuccessful at creating a smaller (generic) project that shows the behavior and there is nothing else I can try, I will have to modify the external libraries.

EDIT
I told our library supplier about the issue and he looked in the K&R C book / C99 standard and pointed out that the switch should work for all int types. Is there a possible deviation from the C specifications with the STM8 compiler? If so I can work around it, I would like to know going forward so I don't end up down this path again on future software releases.

- K&R C: Page 223, a switch takes an "integral" expression.
- K&R C: Page 196, it defines an "integral" type to be 'Types char, and int of all sizes, each with or without sign, and also enumeration types, will collectively be called integral types'.

Thanks for all of the support.

+1
0
-1
August 18, 2011 - 7:25pm
Guest

Any thoughts on this issue?

+1
0
-1
August 25, 2011 - 4:01pm
Raisonance Support Team

Hi,

We have been investigfating this problem in our Labs without any result.
In all the tested cases (signed/unsigned, char/short/int/long/enum) the compiler was emitting correct code.

If you cannot send us the failing project, it is difficult for us to work further on this topic.
However, you can do the following to provide us with a failing portion of code without giving us your source code:
1) Use the PREPRINT compiler directive on the failing file (the C file with the faulty switch). This can be done from the Ride7 project properties in "Compiler options | Listing | Create a preprocessed source")
2) Compile your project. This will generate a ".i" file that contains the preprocessed file with the faulty switch.
3) Rename this .i file to bugswitch.c
4) Create a new Ride7 project, containing only this bugswitch.c, and keep the same project options than in your whole project.
5) Compile this project (it will not link as some functions will be missing)
6) Open the listing file bugswitch.lst and ensure that the problem is present in the assembler generated.
7) Remove unnecessary portions of the file (unused functions), and rename variable/functions in order to protect your code from being stolen.
8) Repeat steps 5-7 until you have a bugswitch.c file that produces the faulty switch, and which hides enough information from your code so that you can share it with us.
9) Send us the bugswitch.c and bugswitch.lst files. We *NEED* the listing file, as it contains the specific "QCW(0x009A6EA0)" instruction that gives us all the information about the compiler options used.

Once we have these files, we will be able to reproduce the problem in our labs and hopefully close this case.
Thanks for your patience,

+1
0
-1
August 25, 2011 - 4:12pm
Guest

Thanks for the update! I will try to get this to you in the next few days. I have been instructed to change the library for the time being, so getting these projects out the door will have top priority. I really wish I could send you the full project, and I am very glad there is a direction that I can still go.