Strange Compiler behaviour

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Strange Compiler behaviour

914 Views
rdazcal
Contributor III

Greetings,

 

I wanted to report a strange compiler behavior that I noticed more than once, and that is really concerning. Please let me know if anyone has noticed it as well, or why this is hapening.

 

I'm using CW6.2, build 080625 and I'm compiling for MC9S08LC36.

 

Once in a while, I notice that when entering a function, the compiler "forgets" to place the function parameter in the stack. Take this function as an example:

 

 

void perif_LC60_configureSerial (ConfigureSerial *ConfigSerial){        SCIC2 = 0x00;          (void)(SCIS1 == 0);    (void)(SCID == 0);         SCIBDH = ConfigSerial->scibdh;    SCIBDL = ConfigSerial->scibdl;        SCIC1 = ConfigSerial->scic1.registrador;    SCIC3 = ConfigSerial->scic3.registrador;    SCIC2 = ConfigSerial->scic2.registrador; }

 

 

In this function, the compiler only stores the return address in the stack, and not the parameter. So I get e freekish behaviour: (*ConfigSerial) actually points to the return address of the function!! Of course it will have random values.

 

To correct this behaviour, I added the following line before SCIC2 = 0x00:

"ConfigureSerial dummy = (*ConfigSerial);"

 

That is enough for me to force the compiler to recognize the parameter.

 

It looks like a serious compiler bug, and I have seen it in other functions as well. It actually appeared in a function I was not working on, which makes me verry suspicious on the whole program... I might get completly unexpected behaviors!

 

Does anyone has a clue on what the problem is? Is it a compiler optimization issue?

 

I apreciate the help

Labels (1)
0 Kudos
5 Replies

362 Views
rdazcal
Contributor III

I figured out what was going on in this particular case.

 

Turns out the program was running fine. I was being missled by the debugger.

 

As I saw, the function parameter was not being stored in stack, and that confused the debbuger that "thought" the value in the stack was ConfigSerial, so it was displaying random values.

 

But in practice, analizing the assembly code, it was storing the parameter in the HX register and using it to change the other registers parameters

 

So thanks anyway! Sorry for doubting CW...

 

Although I did find a compiler error associated with this behavior but now I understand what's going on and I can fix it.

0 Kudos

362 Views
CompilerGuru
NXP Employee
NXP Employee

Still filing a feature request to extend the compiler to emit better debug information might be helpful.

In the end the compiler should not claim the variable is on the stack if it is not. Sure not as bad as wrong code being generated, but should be improved non the less.

 

Daniel

0 Kudos

362 Views
Lundin
Senior Contributor IV

Somewhere out in cyberspace, in the world of application notes, there is one describing how CW optimizes parameter passing for the particular MCU. I only have an old Metrowerks version of the doc known as "Tn15" - Technical note 15, "Mixing Assembly and ANSI C Modules in an Application". I have no idea what the modern version of that document is called, but CW works in the same way still.

 

This should be mandatory reading if writing C programs for Freescale MCUs!

 

Here is some text of it for 68HC12 and HCS12:

 

"Example for HC12
When you are using the HC12 compiler, the parameter-passing scheme is the following:
- The caller pushes the arguments from left to right. After the call, the caller removes the
parameters from the stack again.
- If the last parameter of a function has a simple type, it is not pushed but passed in a register.
This results in shorter code because pushing the last parameter can be saved. The register used
for parameter passing depends on the type of the last parameter:
- When last parameter is encoded on 1 byte (char), it is passed in register B.
- When last parameter is encoded on 2 byte (int, array), it is passed in register D.
- When last parameter is encoded on 3 byte (far data pointer), it is passed in register X and
B.
- When last parameter is encoded on 4 byte (long), it is passed in register X and D."

0 Kudos

362 Views
CompilerGuru
NXP Employee
NXP Employee

The OP's issue was apparently with the S08, not with a S12, so the details are a bit different.

Anyway, yhe calling convention is described in the compiler manual, in the backend chapter.

Just as one note of caution, they are not identical for the HC08 and for the S08's. The S08 is using H:X more as it supports H:X load/stores for more addressing modes.

 

Daniel

0 Kudos

362 Views
J2MEJediMaster
Specialist I

If there really is a compiler error, please submit an service request on it so that Freescale can fix it. This will make yours--and everyone else's--lives easier.

 

Click here to submit a service request.

 

---Tom

0 Kudos