Ich erhalte beim Compilieren eines größeren Programms folgede Warnung: -------- begin -------- avr-gcc (GCC) 4.1.1 (WinAVR 20070122) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiling: main.c avr-gcc -c -mmcu=atmega8515 -I. -g -O2 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst -std=gnu99 main.c -o main.o C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s: Assembler messages: C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:231: Warning: undefined combination of operands C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:232: Warning: undefined combination of operands Was bedeuted das, und wie bekomme ich das weg ? Die Datei wird anscheinend nach dem Compilieren sofort wieder gelöscht, daher kann ich nicht nachschauen was an Zeile 231 und 232 steht.
Benedikt K. wrote: > Compiling: main.c > avr-gcc -c -mmcu=atmega8515 -I. -g -O2 -funsigned-char > -funsigned-bitfields -fpack-struct -fshort-enums -Wall > -Wstrict-prototypes -Wa,-adhlns=main.lst -std=gnu99 main.c -o main.o > C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s: Assembler messages: > C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:231: Warning: undefined > combination of operands > C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:232: Warning: undefined > combination of operands > Was bedeuted das, Dass dem Assembler die Operanden in einem Befehl oder Ausdruck nicht passen. Sollte bei Compiler-generiertem Code nicht passieren, kann aber natürlich gut und gern bei inline asm passieren. > und wie bekomme ich das weg? Indem du den Fehler beseitigst. ;-) > Die Datei wird anscheinend nach dem Compilieren sofort wieder > gelöscht, daher kann ich nicht nachschauen was an Zeile 231 und 232 > steht. Ja, das ist eine temporäre Datei. Du kannst mit
1 | avr-gcc -S -mmcu=atmega8515 -I. -g -O2 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -std=gnu99 main.c |
den Compiler dazu bringen, den Code lediglich in die Datei main.s zu compilieren und danach seine Tätigkeit zu beenden. (Sonst würde er an dieser Stelle den Assembler rufen.) Diese Datei sollte bis auf den Namen äquivalent zu der genannten Datei sein, sodass du darin an Hand der Zeilennummer den Fehler suchen kannst. Falls dein Makefile eine Regel dafür hat, genügt auch »make main.s«.
Jörg Wunsch wrote: > Sollte bei Compiler-generiertem Code nicht passieren, kann aber > natürlich gut und gern bei inline asm passieren. Es gibt nur kein inline asm, deshalb ja auch die ganze Frage...
> Es gibt nur kein inline asm, ...
Muss dir nicht immer gleich bewusst sein. Die avr-libc erledigt auch
einiges mit inline asm.
Von AVR-GCC 3.4.6 zu 4.1.1 wurden sehr viele Änderungen vorgenommen, die wohl ne Menge Seiteneffekte haben. Insbesondere bei der Optimierung gibts einige Überraschungen (Reordering, manchmal größerer Code). In ner Beta des 4.1.1 hatte bei mir sogar ne harmlose switch Anweisung Assembler-Warnungen erzeugt. Der 4.1.1 muß quasi erst noch reifen, während der 3.4.6 bei mir keinerlei Probleme machte. Mit dem Schalter -save-temps kannst Du Dir die temporären Dateien ansehen. Peter
Peter Dannegger wrote: > Von AVR-GCC 3.4.6 zu 4.1.1 wurden sehr viele Änderungen vorgenommen, > die wohl ne Menge Seiteneffekte haben. Du weißt es ja so genau: welche denn? > Insbesondere bei der Optimierung gibts einige Überraschungen > (Reordering, manchmal größerer Code). Ja, die Optimierung ist komplett neu gefasst worden. Einige deiner früheren Lieblingsbeschwerden scheinen sich in Luft aufgelöst zu haben. Es wird sehr viel mehr 8-bit-Code erzeugt, wo GCC 3.x noch 16-bit-Code erzeugt hat. Darüber magst du aber offenbar nicht mehr sprechen, man kann so wenig jammern drüber. Sorry, langsam geht mir deine Polemik aber auf den Senkel. Die hast du nicht nötig. > In ner Beta des 4.1.1 hatte bei mir sogar ne harmlose switch > Anweisung Assembler-Warnungen erzeugt. Das war ein Problem des (nach wie vor inoffiziellen) ATmega256x- Patches, bei dem wir uns mit dem Autor des Patches mittlerweile einig geworden sind, dass die Warnung einerseits sowieso unzureichend war (da sie nicht alle möglichen Fälle abdecken konnte, in denen sie gerechtfertigt gewesen wäre) und andererseits zu Verwirrung geführt hat an Stellen, wo dies nicht notwendig war. Das heißt nicht, dass Björn sich nicht was dabei gedacht hätte, als er damals diese Warnung in den Assembler gebaut hat: die Sprungtabellen zwischen den beiden 128-KiB-Blöcken sind nicht ganz ohne. Wenn deine jump table aus dem switch aus Versehen doch eine 128-KiB-Grenze schneidet, dann kracht's. Dafür gibt es auch keine Abhilfe, es sei denn, du würdest den Übergang von 16-bit- auf 32-bit-Zeiger (für alles, auch RAM-Adressen) für den ATmega256x bevorzugen. > Der 4.1.1 muß quasi erst noch reifen, während der 3.4.6 bei mir > keinerlei Probleme machte. Unfug, der auch von wiederholter Behauptung deinerseits nicht wirklich richtiger wird. Das mag für GCC 4.0.x noch halbwegs richtig gewesen sein, seither sind aber auch schon Jahre ins Land gegangen. Gegenbehauptung: der GCC 4.1.x optimiert nicht nur deutlich besser, sondern hat auch einige Bugs gefixt, die der 3.x noch hatte. Das Risiko, mit GCC 3.x also Schiffbruch zu erleiden, ist mittlerweile schon größer, als mit den aktuellen Versionen. Keine von beiden Aussagen wirst du weder stichhaltig beweisen noch widerlegen können. Also hör bitte auf, hier FUD zu verbreiten. Zum Thema dieses Threads trägt es sowieso Nullkommanichts bei. Das dürfte einfach was komplett anderes sein. Leider mag uns der OP seinen Quellcode nicht antun, also können wir nur mutmaßen. > Mit dem Schalter -save-temps kannst Du Dir die temporären Dateien > ansehen. Genau wie mit der von mir vorgeschlagenen -S Option.
Jörg Wunsch wrote: > Du weißt es ja so genau: welche denn? Sorry, ist natürlich nur mein ganz persönlicher Eindruck. Es waren halt mehr Anpassungen nötig, wenn ich älteren Code übernommen habe, als bei früheren Versionswechseln (Ich weiß natürlich, es liegt nur an meinen nicht C-Standard konformen Annahmen). > Einige deiner > früheren Lieblingsbeschwerden scheinen sich in Luft aufgelöst zu > haben. Nö, das unerwünschte inlining bei -Os macht er immer noch (ja ich weiß, man kann inlining global verbieten, aber an anderen Stellen möchte man es doch). > Es wird sehr viel mehr 8-bit-Code erzeugt, wo GCC 3.x noch > 16-bit-Code erzeugt hat. Darüber magst du aber offenbar nicht mehr > sprechen, man kann so wenig jammern drüber. Ja, switch geht manchmal sogar 8-bittig. Man darf bloß nicht maskieren, z.B. switch(i&0xF0), dann ists wieder 16-bittig. Ich hatte ja auch einige if-Ausdrücke, die beim 3.4.6 grundlos 16-bittig erweitert wurden, muß die mal überprüfen. Peter
Peter Dannegger wrote: >> Du weißt es ja so genau: welche denn? > Sorry, ist natürlich nur mein ganz persönlicher Eindruck. Es ist offenbar massiv am Optimierer gearbeitet worden. Mein erster persönlicher Eindruck war übrigens völlig gegenteilig zu deinem: knapp 10 % Codeeinsparung. Allerdings arbeite ich (zumindest im Job) in einer komplett anderen Kategorie als du, der du mal irgendwo schriebst, dass du nicht wüsstest, womit du einen ATmega128 auch nur annähernd füllen könntest. Wir lasten einen ATmega1281 gut aus, RAM-mäßig auf jeden Fall, ROM-mäßig so bei 30...50 % zurzeit. > Nö, das unerwünschte inlining bei -Os macht er immer noch ... Inlining ist ja nicht generell unerwünscht. Es kann schließlich zu kleinerem Code führen und damit der Prämisse von -Os entsprechen. Ich habe auch einen Bugreport offen, wo er sich verrechnet hat damit. Was mir bei der Diskussion um diesen Report nur wie ein Seifensieder aufgegangen ist: wenn du Funktionen hast wie diese:
1 | void dosomeasm(uint16_t i) |
2 | {
|
3 | inline asm("do this" "\n\t" |
4 | "and that" "\n\t" |
5 | "and" "\n\t" |
6 | "way" "\n\t" |
7 | "more"
|
8 | :
|
9 | : r(i)); |
10 | }
|
...dann ist das für GCCs Kostenberechnung erst einmal nur eine einzige CPU-Anweisung. Mehr kann er davon nicht sehen. Entsprechend kann er davon einige Kopien inline unterbringen, bevor seiner Meinung nach der Preis für die CALL/RET erreicht ist. So'ne Funktion muss man daher also schlicht
1 | static void dosomeasm(uint16_t) __attribute__((noinline)); |
2 | |
3 | void dosomeasm(uint16_t i) |
4 | {
|
5 | ...
|
6 | }
|
deklarieren. Das "static" ist besonders wichtig, wenn die Funktion ein Kandidat fürs inlining sein sollte (und man es nicht verhindern möchte/muss), andernfalls wird trotz inlining noch eine separate Kopie (für die Benutzung als externes Symbol) bereitgestellt. Aber static gehört sowieso zum guten Programmierstil. Der Unterschied zum GCC 3.x hier ist, dass letzterer bei -Os eben nie versucht hat, Funktionen inline zu erweitern, auch dann nicht, wenn es wirklich kürzeren Code ergeben hätte. Aber wie schon gesagt, wir bewegen uns jetzt vom ursprünglichen Punkt dieses Threads mächtig weit weg.
Was mir bezüglich des neuen Compilers aufgefallen ist: -o2 erzeugt meist einen schnelleren und kleineren Code als -os. Ich weiß nicht was ich gemacht habe, auf jedenfall ist diese Warning jetzt weg. Aktiv wurde auf jedenfall kein inline asm von mir verwendet. Falls doch, dann irgendwo in einem mitgelieferten Makro. Sobald ich diese wieder hinbekomme (ich hatte sowas schon öfters), dann suche ich mal was genau schief läuft.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.