When I compile my project. Errors as below show up.
app.C(1025): error C253: '?L0033': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0032': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0031': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0046': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0046': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0046': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0046': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0034': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0040': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0040': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0040': INTERNAL ERROR (UNDEFINED LABEL) app.C(1025): error C253: '?L0040': INTERNAL ERROR (UNDEFINED LABEL)
If I build the project again after these errors shows up, it builds successfully. What are these errors and how can I resove them?
Thank you all very much.
What is on line 1025 of app.C
It's only a { There are 1030 lines in this file.
.... .... 500 #ifndef MACRO_1 .... .... .... 1018 void funA(void) 1019 { 1020 // funcA 1021 funcB(); 1022 1023 funcC(); 1024 1025 } 1026 1027 #endif 1028 1029 1030 #undef __APP_C__
After some tests, I found a code snippet that will trigger this error.
Save the codes as test.c And type C:\Keil\C51\BIN\C51.exe test.c in the command line.
The errors show up.
C51 COMPILER V8.12 COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2008 *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0015': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0015': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0015': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0015': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL) *** ERROR C253 IN LINE 20 OF TEST.C: '?L0001': INTERNAL ERROR (UNDEFINED LABEL)
C51 COMPILATION COMPLETE. 0 WARNING(S), 12 ERROR(S)
What's wrong with this code? Remove any parts of the code will eliminate the error. I'm debugging a bug in my project. I add a return in the very beginning of the test() function to see if this bug is due to the test() function. Code in this function is nonsense because I'm justing trying to reproduce this error with minimum codes.
void test(int a, int c) { return; if (c == 1 || a > 10) { switch (c) { case(0x35): case(0x80): case(0x99): case(0x88): case(0x89): case(0x8a): case(0x8b): case(0x83): case(0x84): case(0x85): break; default: c = 0; break; } } }
As you say yourself, it is nonsense!
What optimisation level are you using? Your example contains unreachable code, so it could be that the optimisations are getting confused by that...?
Have you looked at the generated assembler?
Just some observations: you got 12 error messages. That happens to be the number of integers between 0x80 and 0x8b. And the sequence of ?L0001 and ?L0015 being mentined in them matches which of the 12 numbers in that range have 'case' statements to themselves, and which don't:
case 0x35 : --------- case 0x80 : '?L0001': default : '?L0015': default : '?L0015': case 0x83 : '?L0001': case 0x84 : '?L0001': case 0x85 : '?L0001': default : '?L0015': default : '?L0015': case 0x88 : '?L0001': case 0x89 : '?L0001': case 0x8a : '?L0001': case 0x8b : '?L0001': case 0x99 : ---------
From this I would conclude that something went belly-up in the compiler while constructing a jump table for this sequence of 12 closely-spaced cases. Looks like it set up the jump table, but the labels it jumps to didn't get generated.
Yes - that's the way I was thinking, too!
"Looks like it set up the jump table, but the labels it jumps to didn't get generated."
Or, perhaps, the optimiser got misled by the unreachable code, and deleted them when it shouldn't have - or deleted them without also removing the references to them.
Anyhow, definitely sound like something for Keil support...
happen when the precompiler conditionals did not match.
However, try this: Set a low optimizer level (I suggest 2) and see if the errors change to something meaningful, if so fix the problem, if the errors go away you have constructed something that the optimizer (although it should) can not handle.
Erik
All errors disappear after lower the code optimization level to 7. Thank you all!
Sounds like a bug that should be reported - or at least a feature that should be properly documented!
Sounds like a bug that should be reported - or at least a feature that should be properly documented! absolutely! as I said "if the errors go away you have constructed something that the optimizer (although it should) can not handle.
anyhow, what do I care, I do not optimize beyond 2 for debuggability. which brings me back to my pet peeve WHY is so much that belong in the compiler done by the optimizer YES, 'common threads is an optimizer job but why does the compiler not itself not 'optimize' mov a,xxx mov r7,a mov a,r7
"WHY is so much that belong in the compiler done by the optimizer"
The optimizer is the compiler.
It's just that the compiler performs it's job in multiple steps.
- Parsing - Constant folding - Strength reductions - ... - Code output - List output
It's just a question of writing modularized code, i.e. standard software engineering best practices. It would not be fun to maintain a compiler that performed its optimization/code generation on-the-fly at the parsing stage!
In some special cases, the front-end, optimizer and one or more back-ends have been split into separate binaries but they still form "the compiler".
let us not argue words. if you want it in another form it should be possible to get all possible optimization that does not affect program flow ("mov a,r7" jump table switches etc) without program flow (sequence combining) optimization for the simple reason of debuggability with the best possible debuggable code.
The optimizer is the compiler. as far as i know, a lot of optimizationis are done by the linker.
"The optimizer is the compiler. as far as i know, a lot of optimizationis are done by the linker."
Yes, a "tribute" to the ugly duckling. That's an exceptions to the rule and more or less a required workaround since the '51 architecture was optimized for a minimal transistor count. Most contemporary processors had the same number of transistors for just the processor core, without any timer, serial port, ...
Most compilers can define 'global optimization' as optimization within a single source file, and doesn't have to fight so desperately to convert auto variables to reused global variables.
In this case, Keil has moved a significant part of the traditional back-end into the linker.
my peeve is not related to where the optimization is, but with the inability to select "optimize everything that does not affect debugging, and nothing else". Now this may sound stupid, but if you have e.g. a timing error that show when the code is not debuggable (in the ICE) and does not show when the code is debuggable (in the ICE) you will waste an inordinate amount of time debugging by "othere means".
It is not a 'preference' issue it is a 'productivity' issue. Any bug that is simple to find the value of the ICE is not huge, but it seems that the bugs where that ICE is of great vaiue are those that only show up when optimized.
I have solved the issue by simply not selecting any optimization beyond two, this may lead to a module or two being coded in assembler which might not have been needed was the optimizer usable.