191 views
in Embedded Wizard Studio by

Hi all,

I just upgraded from EW9.0 to EW11. I started this just before EW12 was released...

EW11 does compile some strange things with an assignment of the most negative int32 number...

The code was:

//cura
var int32 val32 = 0;
val32 = (int32)0x80000000;

So this is the most negative number in twos-complement.

It generates following c-code:

//c
XInt32 val32;
val32 = -(int)2147483648;

But why is this typecast there? this splits the integer-literal into two parts. Now it takes 2147483648 as a positive number and after casting it to (int), it builds the negative of it:

-(int)2147483648 //is interpreted as follows:
-((int)2147483648)
the positive number 2147483648 overflows to -2147483648, so the expression is now:
-(-2147483648) = 2147483648
that again will overflow to
-2147483648

but the initial overflow will trigger a warning in gcc:

warning: integer overflow in expression '-2147483648' of type 'int' results in '-2147483648' [-Woverflow]

I tried to work-around with changing the strange hex-to-int-cast to the actual integer value:

//cura
val32 = -2147483648

but now even ew studio complaints:

Warning Application::parentService.onPressButton (11:11) : Unary minus operator applied on unsigned operand 'uint32'. This may cause an overflow. Therefore the resulting value is considered as being still unsigned 'uint32'. To suppress the warning prefix the operand by the type cast operator (int32), e.g. -(int32)(operand).

the resulting c-code is again:

//c
val32 = -(int)2147483648;

When following the suggestion of adding the cast-operator:

//cura
val32 = -(int32)2147483648;

then, the warning in ew-studio is gone, but the same c-code is built:

//c
val32 = -(int)2147483648;

Thus the gcc overflow-warning is still present.

I would understand, that my strange cast from the beginning ((int32)0x80000000) is hacky. But why on earth i could not enter a simple negative integer literal? Why is the minus interpreted as an unary operator?

Greetings Daniel

2 Answers

0 votes
by
 
Best answer

If someone stumbles over this, here is a workaround: i have written a python-script as workaround, that has to be added as PostProcess command in the Profile:

PostProcess = "py -3 fix_negative_overflow_bug.py"
#this is fix_negative_overflow_bug.py in the project root folder

import os
import glob

path = os.path.join(os.environ['EmWi_OutputDirectory'], "*.c")

for f in glob.glob(path):
	with open(f, "r") as inputfile:
		newText = inputfile.read().replace('-(int)2147483648', '-2147483648')

	with open(f, "w") as outputfile:
		outputfile.write(newText)

 this replaces all occurences of '-(int)2147483648' with '-2147483648' in all c-files in the output directory.

0 votes
by

Hello Daniel,

thank you very much for reporting this issue. I have analysed the conditions more in detail. Following are the results:

1. In Embedded Wizard version 10 we have modified the Code Generators to handle explicitly the negative value -2147483648. In such case the expression -(int)2147483648 is generated.

2. This modification was necessary to suppress C compiler warnings. When the expression -2147483648 is found in C code, the C compiler reports following warning:

The C compiler promotes in such case the value 2147483648 to unsigned int since it is too large to fit inside a signed int. The preceding - sign is considered as unary minus operator by the C compiler.

3. With the version 10 we have also adapted the Chora compiler to consequently report similar warnings as the C compilers do.

4.  This behaviour corresponds to C90 standard. With C99 standard the literal 2147483648 is considered as long long (64 bit) value. Since it remains signed the unary minus operator is not an issue in this case. The C99 compiler does not report any warning.

5. There is a peculiarity with 32 bit integers. The unsigned int value 2147483648 is bitwise equal to signed int value -2147483648. According to found C documentation the signed int value -2147483648 should be entered using the expression (int)2147483648. The minus unary operator is not needed.

6. Embedded Wizard Code Generator, however, prepends in the resulting code the expression with the - minus operator (e.g. -(int)2147483648). This is incorrect. 

7. When processing the literal -2147483648, the Chora compiler follows the C90 standard and reports warnings because of the unary operator used on the unsigned int operand. From actual point of view, this limitation is not necessary.

According to the above analysis, the actual behaviour corresponds to C90 standard. The unary minus operator in the generated code (item 6) is superfluous, although it has no effect on the resulting expression. To suppress the Chora and C compiler warnings we will modify the behaviour:

8. The preceding minus operator in the generated code will be removed when generating the literal -2147483648. It will produce (int)2147483648 only.

9. Chora compiler will be adapted to not report a warning when the literal -2147483648 is processed.

We will correct the functionality in the next version. Unfortunately I was not able to elaborate a workaround for the problem working with the actual EW version. I see only following two possibilities for the moment:

1. Ignore the C compiler overflow warning. The resulting value should still be correct.

2. If possible in your application case, use the value -2147483647

I hope it's not a big obstacle to your work.

Best regards

Paul Banach

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...