Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ppci-cc : incorrect IR module generated with -O 2 #47

Closed
tstreiff opened this issue Jan 15, 2020 · 6 comments
Closed

ppci-cc : incorrect IR module generated with -O 2 #47

tstreiff opened this issue Jan 15, 2020 · 6 comments
Assignees
Labels

Comments

@tstreiff
Copy link
Contributor

When compiling the following C code with "ppci-cc -O 2 xxx.c", an unexpected error is reported
void g(int n);

void f() {
int i;
g(i);
}
Here is the progress report :
2020-01-15 22:59:12,590 | INFO | root | ppci 0.5.7 on CPython 3.6.9
2020-01-15 22:59:12,601 | INFO | cbuilder | Starting C compilation (c99)
2020-01-15 22:59:12,607 | INFO | cparser | Parsing finished
2020-01-15 22:59:12,610 | INFO | ccodegen | Finished IR-code generation
2020-01-15 22:59:12,612 | INFO | optimize | Optimizing module main level 2
2020-01-15 22:59:12,614 | ERROR | root | und_i_alloc = undefined is used
2020-01-15 22:59:12,614 | ERROR | root | None
und_i_alloc = undefined is used
I dig a bit and saw that the problem is reported by the IR verifier in irutils.py.
It reports that instruction "undefined" has been found in the module.
The instruction is apparently inserted by the "mem2reg promotor" during the optmizer pass.
This is why the problem does not occur when compiling with -O 0.
Note that if variable "i" is assigned a value before calling "g", the problem does not happen. If this comes from this, it should be reported in a clearer way.

@windelbouwman
Copy link
Owner

Thanks for submitting this issue! I faced this before, and did not know what to do. What should the behavior be here? Should we just allocate a register for i and leave it uninitialized?

@tstreiff
Copy link
Contributor Author

From the user point of view, it looks very like a compiler bug.
For me an optimization should not change the external behaviour.
The best would be to do as you propose : to allocate a register and leave it uninitialized because this is what will happen on the local variable without the optimization.
But if possible warn the user (use of uninitialized local variable)

@pfalcon
Copy link
Contributor

pfalcon commented Jan 16, 2020

Funny thing is that gcc doesn't warn that by default:

#include <stdio.h>

int main()
{
    int i;
    printf("%d\n", i);
    printf("%d\n", i + 4);
}

clang follows, apparently because doing otherwise may break something.

The best would be to do as you propose : to allocate a register and leave it uninitialized

und_i_alloc = undefined

I guess it's about what happens in PPCI, just this special "undefined" value isn't handled in all places. Note that use of uninitialized value is undefined behavior, so anything would work. Ideal solution IMHO would be: without optimization, treat "undefined" as some specific value. 0 seems like a good choice, 0xdeadbeef would work too, though decimal of that may be surprising to user. And with high optimization level, just employ the rule that any operation on undefined is itself undefined behavior, so may produce any result. That for example may mean selecting smallest/fastest machine opcode. E.g. suppose *b = a + undefined is codegenerated, and b is in EBX. Then asm op would be mov [ebx], random_reg, e.g. mov [ebx], eax, where eax is chosen mostly randomly. clang follows this logic with -O2:

$ clang-8 -O2 uninit.c 
pfalcon@zenbook:~/tmp$ ./a.out 
-112910488
39068256

gcc -O2 isn't brave enough ;-).

@tstreiff
Copy link
Contributor Author

I am facing the same problem with the following program. But this time, the "undefined" variable "k" is always defined before being used. The reason for the "undefined" is therefore different.

void f() {
int i, j, k;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
for (k = 0; k < 10; k++) {
printf("i=%d j=%d k=%d\n", i, j, k);
}
}
}
}
2020-01-22 23:38:17,346 | INFO | root | ppci 0.5.7 on CPython 3.6.9 on Linux
2020-01-22 23:38:17,352 | INFO | cbuilder | Starting C compilation (c99)
2020-01-22 23:38:17,374 | INFO | cparser | Parsing finished
2020-01-22 23:38:17,377 | INFO | ccodegen | Finished IR-code generation
2020-01-22 23:38:17,378 | INFO | optimize | Optimizing module main level 2
2020-01-22 23:38:17,384 | ERROR | root | und_k_alloc = undefined is used
2020-01-22 23:38:17,384 | ERROR | root | None
und_k_alloc = undefined is used

@windelbouwman windelbouwman self-assigned this Jun 8, 2020
@windelbouwman
Copy link
Owner

This issue is addressed in f361257

Approach is taken to define a register (with some random contents).

@tstreiff
Copy link
Contributor Author

I checked the 2 programs above which compilation were not possible with -O 2.
It now works, we may close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants