=== GCC v15 ===

OP Persönliche Seite #7868376
Lesenswert?

Die diesjährige GCC Release v15 ist raus: https://gcc.gnu.org/gcc-15/changes.html

Per Default wird C als C23 übersetzt. Ein paar Neuerungen:

  • constexpr für Objekte. Kann z.B. für Array-Größe verwendet werden.

  • Direktive #embed, mit der man Binärdateien ins Programm einfügen kann. Das ging bislang schon, war aber z.T. umständliches Binutils Gebastel. Beispiel mit #embed:

1
#include <stdio.h>
2
#include <avr/pgmspace.h>
3
 
4
static const char foo_c[] PROGMEM =
5
{
6
#embed "foo.c"
7
    // Append \0 so that foo_c becomes a proper C string
8
    // (assuming foo.c is a text file).
9
    , '\0'
10
};
11
 
12
int main ()
13
{
14
    printf ("== foo.c has %d bytes ==\n%S\n",
15
            (int) sizeof (foo_c) - 1, foo_c);
16
}
  • bool, true und false sind Schlüsselworte. stdbool.h wird nicht mehr gebraucht, funktioniert aber weiterhin.

  • Globale asm Statements können Argumente haben.

  • In Prototypen wie "int func()" ist "()" gleichbedeutend mit "(void)".

  • Case Ranges (-std=c2y)

  • if Deklarationen so wie in for (-std=c2y)

  • Implizite Oktal-Literals sind abgeschafft. Wer wirklich 12 oktal will schreibt also nicht mehr 012 sondern 0o12.

Auch für AVR gibt es ein paar Neuerungen:

https://gcc.gnu.org/gcc-15/changes.html#avr

  • Attribute signal(num) wo num die IRQ-Nummer ist. Damit kann man static Funktionen als ISR verwenden und auch Funktionen aus einem C++ Namespace. AVR-LibC v2.3 uterstützt das als ISR_N(num). Beispiel:
1
#include <avr/io.h>
2

3
__attribute__((signal(ADC_vect_num)))
4
static void adc_isr (void)
5
{
6
   // Code
7
}
8

9
#include <avr/interrupt.h>
10

11
ISR_N (INT0_vect_num) // ab AVR-LibC v2.3
12
static void int0_isr (void)
13
{
14
   // Code
15
}
  • Unterstützung von Compact Vector Table (CVT). Auch dies erfordert AVR-LibC v2.3.

AVR-LibC v2.3 ist noch nicht released. News: https://github.com/avrdudes/avr-libc/blob/main/NEWS.md (Links auf neue Header sind 404 weil die aktuelle Doku noch für v2.2 ist.)

#7868596
Lesenswert?

Johann L. schrieb:

  • Implizite Oktal-Literals sind abgeschafft. Wer wirklich 12 oktal will schreibt also nicht mehr 012 sondern 0o12.

Vielen Dank für die Warnung. Wer war das? 0.2% meiner Quelltextzeilen müssen geändert werden, muss das sein? Brauchen die alle kein chmod(), open(), creat()... oder ANSI-Escapes? Funktioniert denn jetzt zum Ausgleich wenigstens '\e' statt '033'?

Kennt der gcc 13 oder 14 diese Konstruktion schon?

1
$ gcc --version
2
gcc (Debian 12.2.0-14) 12.2.0
3
$ make
4
mkpdfs.c: In function 'mktmpdir':
5
mkpdfs.c:192:23: error: invalid suffix "o755" on integer constant
6
  192 |    if (mkdir (tmpdir, 0o755)) {
7
      |                       ^~~~~
OP Persönliche Seite #7868674
Lesenswert?

Bauform B. schrieb:

Johann L. schrieb:

  • Implizite Oktal-Literals sind abgeschafft. Wer wirklich 12 oktal will schreibt also nicht mehr 012 sondern 0o12.

Vielen Dank für die Warnung. Wer war das?

WG14 Vorschlag N3193 "Obsolete implicitly octal literals" ist zum Beispiel hier zu finden: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3193.htm

The use of base-8 instead of base-10 by integer literals that begin with a zero digit is the source of frequent confusion. We propose marking the use of such literals as obsolete in order to encourage a warning that will prompt rewrites, and the introduction of a new prefix to explicitly mark literals that are genuinely intended to be in base-8.

und:

We propose that a new syntax is added for explicit octal constants, with a new prefix 0o or an alternative spelling to mark the beginning of a base-8 literal. The old syntax should be retained and marked as obsolescent to avoid breaking the meaning of existing code.

Wie es aussieht wird es eine neue Diagnostic geben, die auch deaktiviert werden kann wenn man die alte Syntax wirklich haben will (ähnlich zu Trigraphen).

Kennt der gcc 13 oder 14 diese Konstruktion schon?

Das hängt weniger am Compiler als an der C-Version, welche noch nicht released ist. C2y wird wohl C26 oder C27 werden. In C23 ist es als Erweiterung drin, aber erst ab GCC v15:

1
$ echo 'int i = 0o12;' | gcc-14 -xc - -fsyntax-only -std=c23
2
<stdin>:1:9: error: invalid suffix "o12" on integer constant
3
$ echo 'int i = 0o12;' | gcc-15 -xc - -fsyntax-only -std=c23 # ok
4
$ echo 'int i = 0o12;' | gcc-15 -xc - -fsyntax-only -Wpedantic
5
<stdin>:1:9: warning: '0o' prefixed constants are a C2Y feature or GCC extension [-Wpedantic]
6
$ echo 'int i = 0o12;' | gcc-15 -xc - -fsyntax-only -std=c2y -Wpedantic # ok

Compiler Explorer https://godbolt.org/ kennt auch schon GCC v15.1 wenn du was ausprobieren willst.

Zum Portieren auf eine neue GCC Version gibt es auch immer Porting Notes:

https://gcc.gnu.org/gcc-13/porting_to.html https://gcc.gnu.org/gcc-14/porting_to.html https://gcc.gnu.org/gcc-15/porting_to.html

#7868789
Lesenswert?

Johann L. schrieb:

Die diesjährige GCC Release v15 ist raus: https://gcc.gnu.org/gcc-15/changes.html

Vielen Dank!

Habe gerade paar meiner Projekte damit und aktueller avr-libc (git) durchgebaut. Generierter code scheint, bei mir, mit dem gcc-15.1 deutlich kleiner zu sein als gcc-14.2. An gcc-13.1 kommt er allerdings nicht heran.

Trotzdem, vielen Dank noch mal fuer den unglaublichen Einsatz!

Wie wird uebrigens das hier funktionieren:

  • Unterstützung von Compact Vector Table (CVT). Auch dies erfordert AVR-LibC v2.3.

In den neuen gcc/ld manpages habe ich nichts dazu gefunden. Wird es automatisch passieren, oder wird man sich dazu linker-command-files selber stricken muessen?

-Foka

OP Persönliche Seite #7868809
Lesenswert?

Foka M. schrieb:

Generierter code scheint, bei mir, mit dem gcc-15.1 deutlich kleiner zu sein als gcc-14.2. An gcc-13.1 kommt er allerdings nicht heran.

Da wäre interessant zu sehen, wo es da hakt (also Testfall, Optionen etc.)

Wie wird uebrigens das hier funktionieren:

  • Unterstützung von Compact Vector Table (CVT). Auch dies erfordert AVR-LibC v2.3.

In den neuen gcc/ld manpages habe ich nichts dazu gefunden.

https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gcc/AVR-Options.html#index-mcvt

Linker und Linkerscript sind unverändert.

  1. libc configure stellt fest, welche Devices CVT können.

  2. Für entsprechende Devices gibt es eine neue Build-Variante crt<mcu>-cvt.o des Startup-Codes, der ja die Vectab mitbringt.

  3. Welcher Startup-Code gelinkt wird entscheidet der Compiler anhand von -mcvt: crt<mcu>.o oder crt<mcu>-cvt.o.

  4. crt<mcu>-cvt.o referenziert Code, der CVT aktiviert (in .init3). Man braucht CVT also nicht händisch zu aktivieren.

https://github.com/avrdudes/avr-libc/blob/main/libc/misc/init_cvt.S

Falls man CVT selbst aktivieren möchte, dann definiert man Symbol __init_cvt so dass der Code nicht mehr aus der Devicelib gezogen wird.

crt<mcu>-cvt.o kann man natürlich auch mit älteren GCC Versionen verwenden, hat dann aber nicht den Comfort von -mcvt.

#7868819
Lesenswert?

Johann L. schrieb:

Foka M. schrieb:

Generierter code scheint, bei mir, mit dem gcc-15.1 deutlich kleiner zu sein als gcc-14.2. An gcc-13.1 kommt er allerdings nicht heran.

Da wäre interessant zu sehen, wo es da hakt (also Testfall, Optionen etc.)

Ich versuche mal am kommenden langen WoE etwas mehr Inhalte zusammen zu bekommen. Compiler wird aufgerufen mit (nur ein Beispiel):

1
avr-15.1.0/bin//avr-g++ -c -DF_CPU=4000000UL -DF_CLOCK=4000000UL \
2
-DCONFIG_H=\"config_atmega328p.h\" \
3
-I. -I../ -I../avrUtils -I../avrUtils/com -I../avrUtils/common/ -I./ \
4
-Os -g -mmcu=atmega328p -flto -mstrict-X -mrelax -maccumulate-args \
5
-mcall-prologues -funsigned-char -funsigned-bitfields \
6
-ffunction-sections -fdata-sections -fshort-enums -fno-strict-aliasing \
7
-Wall -Wextra -Wundef -Wunreachable-code -Wsign-compare \
8
-fno-threadsafe-statics -std=c++20 -MMD -MP -MF .dep/AvrAsyncTimer.o.d \
9
../Fio/avr/AvrAsyncTimer.cpp -o objs/AvrAsyncTimer.o

Ich mache vorwiegend C++ und bin gerade auf C++20 festgenagelt. Die Unterschiede koennten also auch hieraus entstehen. Auch wenn der gcc-13 schon so ziemlich "feature complete" gewesen ist.

Wie wird uebrigens das hier funktionieren:

  • Unterstützung von Compact Vector Table (CVT). Auch dies erfordert AVR-LibC v2.3.

In den neuen gcc/ld manpages habe ich nichts dazu gefunden.

https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gcc/AVR-Options.html#index-mcvt

Oh, richtig. Habe ich in der manpage echt uebersehen. Danke fuer die Erklaerung. Das WoE wird echt zu kurz ;-)

-Foka

OP Persönliche Seite #7868852
Lesenswert?

Foka M. schrieb:

1
> avr-g++ ... -flto ... -o objs/AvrAsyncTimer.o

Mit LTO genügt zum Nachvollziehen nicht mehr das Präcompilat eines Moduls (z.B. mit -save-temps), weil *.o nur LTO-Bytecode enthält. (-ffat-lto-objects hilft auch nix, weil nicht-LTO Code zur lto Time verworfen wird).

Mit LTO braucht man also (die Präcompilate) alle(r) Module, um was nachzuvollziehen. Evtl lässt sich mit -fno-lto eingrenzen, wo der Codezuwachs herhommt. Wenn er nur mit -flto passiert ist es ein Indiz dafür, dass sich was beim IPA geändert hat (Inlining, Cloning, LTO-Partitioning, etc.).

#7868900
Lesenswert?

Johann L. schrieb:

Foka M. schrieb:

1
>> avr-g++ ... -flto ... -o objs/AvrAsyncTimer.o

Mit LTO genügt zum Nachvollziehen nicht mehr das Präcompilat eines Moduls (z.B. mit -save-temps), weil *.o nur LTO-Bytecode enthält. (-ffat-lto-objects hilft auch nix, weil nicht-LTO Code zur lto Time verworfen wird).

Ich habe jetzt das gleiche ohne lto gemacht. Geiches Projekt, gleiche compile optionen, in beiden Faellen ohne lto. gcc-13.1:

1
Sections:
2
Idx Name          Size      VMA       LMA       File off  Algn
3
  0 .data         00000050  00800100  00001b0c  00001bc0  2**0
4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
5
  1 .text         00001b0c  00000000  00000000  000000b4  2**1
6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
7
  2 .bss          00000091  00800150  00800150  00001c10  2**0

gcc-15.1:

1
Sections:
2
Idx Name          Size      VMA       LMA       File off  Algn
3
  0 .data         00000050  00800100  00001b7e  00001c32  2**0
4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
5
  1 .text         00001b7e  00000000  00000000  000000b4  2**1
6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
7
  2 .bss          00000091  00800150  00800150  00001c82  2**0

Das sind, bei ca. 7kB in .text, 114Byte Unterschied zu Gunsten des gcc-13.1.

Wie gesagt, ich werde mir am WoE die einzelnen Objekte ansehen, und melde mich wieder falls ich etwas greifbareres habe.

-Foka

OP Persönliche Seite #7869391
Lesenswert?

Rolf M. schrieb:

Johann L. schrieb:

Wer wirklich 12 oktal will schreibt also nicht mehr 012 sondern 0o12.

Hmm, dann kann man jetzt endlich die 0 in dezimal schreiben. 😀

Nicht mal das. N3193:

Zero remains a traditional octal constant

Da oktal in MISRA absolut verboten ist, darf man also immer noch nicht "x = 0;" schreiben sondern muss weiterhin "x = 1-1;" o.ä.

#7869411
Lesenswert?

Foka M. schrieb:

Johann L. schrieb:

Foka M. schrieb:

1
>>> avr-g++ ... -flto ... -o objs/AvrAsyncTimer.o

Mit LTO genügt zum Nachvollziehen nicht mehr das Präcompilat eines Moduls (z.B. mit -save-temps), weil *.o nur LTO-Bytecode enthält. (-ffat-lto-objects hilft auch nix, weil nicht-LTO Code zur lto Time verworfen wird).

Wie gesagt, ich werde mir am WoE die einzelnen Objekte ansehen, und melde mich wieder falls ich etwas greifbareres habe.

Ich habe jetzt mal paar Codestellen die gcc-15.1 dicker macht genauer angesehen. Zum einen muss ich zu geben, dass ich die gcc-13.1 und 15.1 tool-chains mit verschiedenen avr-libc Versionen gebaut habe. Dummerweise beide direkt auf dem, damaligen, git-master basierend. Dh. um wirklich fundierte Vergleiche zu bekommen muesste ich beide compiler mit der gleichen avr-libc verwenden.

Mir fiel jedoch auf, dass der gcc-15.1 sich mehr um den stack pointer 'kuemmert' und dazu neigt prologue/epilogue fetter zu machen. Hier mal eine kleine Funktion die zwei bytes auf SPI schreibt. Eigentlich sollte es nur CS-ziehen, zwei mal txRaw (schreibt einen byte und wartet auf fertig) aufrufen und dann wieder CS los lassen.

Beim gcc-13.1 sieht es so aus ('//' sind meine kommentare):

1
#    template <class Locker = DefaultLockTypeT>
2
#    static uint8_t               txCmd( uint8_t _cmd, uint8_t _byte ) {
3
     3d8:  cf 93         push  r28
4
     3da:  c6 2f         mov  r28, r22
5
     3dc:  40 98         cbi  0x08, 0  ; 8  // pull CS
6
     3de:  f5 df         rcall  .-22       ; 0x3ca <Fl::AvrIO::AvrSpiMaster<Fl::AvrIO::PinX<(unsigned char)0, Fl::AvrIO::PortX<38> > >::txRaw(unsigned char)>
7
     3e0:  8c 2f         mov  r24, r28
8
     3e2:  f3 df         rcall  .-26       ; 0x3ca <Fl::AvrIO::AvrSpiMaster<Fl::AvrIO::PinX<(unsigned char)0, Fl::AvrIO::PortX<38> > >::txRaw(unsigned char)>
9
     3e4:  40 9a         sbi  0x08, 0  ; 8  // release CS
10
     3e6:  cf 91         pop  r28
11
     3e8:  08 95         ret

Der gcc-15.1 macht daraus:

1
#    template <class Locker = DefaultLockTypeT>
2
#    static uint8_t               txCmd( uint8_t _cmd, uint8_t _byte ) {
3
     3e8:  a1 e0         ldi  r26, 0x01  ; 1
4
     3ea:  b0 e0         ldi  r27, 0x00  ; 0
5
     3ec:  ea ef         ldi  r30, 0xFA  ; 250
6
     3ee:  f1 e0         ldi  r31, 0x01  ; 1
7
     3f0:  0c 94 4c 0d   jmp  0x1a98  ; 0x1a98 <.Loc.16>
8
     3f4:  69 83         std  Y+1, r22  ; 0x01
9
     3f6:  40 98         cbi  0x08, 0  ; 8  // pull CS
10
     3f8:  f0 df         rcall  .-32       ; 0x3da <Fl::AvrIO::AvrSpiMaster<Fl::AvrIO::PinX<(unsigned char)0, Fl::AvrIO::PortX<38> > >::txRaw(unsigned char)>
11
     3fa:  89 81         ldd  r24, Y+1  ; 0x01
12
     3fc:  ee df         rcall  .-36       ; 0x3da <Fl::AvrIO::AvrSpiMaster<Fl::AvrIO::PinX<(unsigned char)0, Fl::AvrIO::PortX<38> > >::txRaw(unsigned char)>
13
     3fe:  40 9a         sbi  0x08, 0  ; 8  // release CS
14
     400:  21 96         adiw  r28, 0x01  ; 1
15
     402:  e2 e0         ldi  r30, 0x02  ; 2
16
     404:  0c 94 68 0d   jmp  0x1ad0  ; 0x1ad0 <.Loc.16>

In .Loc.16 ist eine sub-routine die den SREG rettet, interrupts stoppt, stack pointer runter schiebt, und dann den SREG wieder zurueck holt (gcc-15.1):

1
00001ad0 <.Loc.16>:
2
    1ad0:  aa 81         ldd  r26, Y+2  ; 0x02
3
    1ad2:  b9 81         ldd  r27, Y+1  ; 0x01
4
    1ad4:  ce 0f         add  r28, r30
5
    1ad6:  d1 1d         adc  r29, r1
6
    1ad8:  0f b6         in  r0, 0x3f  ; 63
7
    1ada:  f8 94         cli
8
    1adc:  de bf         out  0x3e, r29  ; 62
9
    1ade:  0f be         out  0x3f, r0  ; 63
10
    1ae0:  cd bf         out  0x3d, r28  ; 61
11
    1ae2:  ed 01         movw  r28, r26
12
    1ae4:  08 95         ret

Klingt plausiebel. Aber ich frage mich, warum der gcc-13.1 das nicht macht. Sind im neuen GCC vielleicht irgendwelche stack pointer Schutzmechanismen eingebaut worden die jetzt mehr speicher verbrauchen?

Der gcc-13.1 schiebt den stack pointer natuerlich auch immer wieder herum. Aber vor allem dann, wenn eine groessere sub-routine (oder mehrere davon) aufgerufen wird. Ich habe kaum Stellen gesehen an den es so aufwaendig gemacht wird, obwohl die sub-routine wirklich so banal ist wie mein txRaw oben.

Falls es etwas bringt, kann ich den generierten code fuer die kleine txRaw auch posten.

Ich habe noch paar andere Stellen gefunden, an den der gcc-15.1 sich dem stack pointer mehr zuwendet. Es ist etwas weniger aufwaendig wie oben und ist vollstaendig, ohne 'jump', in den prologue der Funktion eingebettet. Allerdings macht an der gleichen Stellen der gcc-13.1 nichts weiter als nur den Stackpointer zu speichern, was viel weniger aufwaendig und damit kuerzer ist. Hier ein Auszug aus einer etwas groesseren Funktion. Nur der prologue. gcc-13.1:

1
# RadioHandler<PolicyT, IsrImpl>::receivePingRequest(){
2
     bd6:  cf 92         push  r12
3
     bd8:  df 92         push  r13
4
     bda:  ef 92         push  r14
5
     bdc:  0f 93         push  r16
6
     bde:  1f 93         push  r17
7
     be0:  cf 93         push  r28
8
     be2:  df 93         push  r29
9
     be4:  00 d0         rcall  .+0        ; 0xbe6 <L0^A>
10
00000be6 <L0^A>:
11
     be6:  00 d0         rcall  .+0        ; 0xbe8 <L0^A>
12
00000be8 <L0^A>:
13
     be8:  00 d0         rcall  .+0        ; 0xbea <L0^A>
14
00000bea <L0^A>:
15
     bea:  cd b7         in  r28, 0x3d  ; 61  // store spl
16
     bec:  de b7         in  r29, 0x3e  ; 62  // store sph
17
     bee:  6c 01         movw  r12, r24
18

19
00000bf0 <.Loc.879>:
20
#    RxData<PacketType::PingRequestPkt> rxData{mRxMetaData.mRxData};
21
     bf0:  fc 01         movw  r30, r24
22
     bf2:  a3 85         ldd  r26, Z+11  ; 0x0b  // ab hier alles wieder gleich
23
     bf4:  b4 85         ldd  r27, Z+12  ; 0x0c
24
...

Dagegen gcc-15.1 ('//' wieder von mir):

1
# RadioHandler<PolicyT, IsrImpl>::receivePingRequest(){
2
     c50:  ef 92         push  r14
3
     c52:  0f 93         push  r16
4
     c54:  1f 93         push  r17
5
     c56:  cf 93         push  r28
6
     c58:  df 93         push  r29
7
     c5a:  cd b7         in  r28, 0x3d  ; 61  // store spl
8
     c5c:  de b7         in  r29, 0x3e  ; 62  // store sph
9
     c5e:  28 97         sbiw  r28, 0x08  ; 8  // reduce stack pointer by 8
10
     c60:  0f b6         in  r0, 0x3f  ; 63  // sreg write
11
     c62:  f8 94         cli        // shut up
12
     c64:  de bf         out  0x3e, r29  ; 62  // restore sph
13
     c66:  0f be         out  0x3f, r0  ; 63  // restore sreg
14
     c68:  cd bf         out  0x3d, r28  ; 61  // restore spl
15
     c6a:  8f 83         std  Y+7, r24  ; 0x07
16
     c6c:  98 87         std  Y+8, r25  ; 0x08
17

18
00000c6e <.Loc.872>:
19
#    RxData<PacketType::PingRequestPkt> rxData{mRxMetaData.mRxData};
20
     c6e:  fc 01         movw  r30, r24
21
     c70:  a3 85         ldd  r26, Z+11  ; 0x0b  // ab hier alles wieder gleich
22
     c72:  b4 85         ldd  r27, Z+12  ; 0x0c

Ist es moeglich dem gcc-15.1 etwas schlankere Funktionsaufrufe beizubringen? Ich habe das Gefuel, dass ich, zumindest in meinem Code, einiges sparen koennte.

-Foka

OP Persönliche Seite #7869504
Lesenswert?

Foka M. schrieb:

Zum einen muss ich zu geben, dass ich die gcc-13.1 und 15.1 tool-chains mit verschiedenen avr-libc Versionen gebaut habe.

Spielt auf der Ebene keine Rolle.

In .Loc.16 ist eine sub-routine die den SREG rettet, interrupts stoppt, stack pointer runter schiebt, und dann den SREG wieder zurueck holt (gcc-15.1):

Das ist __epilogue_restores

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libgcc/config/avr/lib1funcs.S;h=dfe99b1ea06f5b45e0a19942c42fe92f46e497ac;hb=HEAD#l2241

das Gegenstück zu __prologue_saves

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libgcc/config/avr/lib1funcs.S;h=dfe99b1ea06f5b45e0a19942c42fe92f46e497ac;hb=HEAD#l2188

Beide können verwendet werden wenn -mcall-prologues an ist.

Aber ich frage mich, warum der gcc-13.1 das nicht macht.

Weil, wie du bereitst feststelltest, v15 mehr Stack beansprucht.

Falls es etwas bringt, kann ich den generierten code fuer die kleine txRaw auch posten.

Den generierten Code seh ich ja. Bestenfalls könnte man mit dem Präcompilat (*.ii von -save-temps) was anfangen.

Ist es moeglich dem gcc-15.1 etwas schlankere Funktionsaufrufe beizubringen?

Da es sich um den Register-Allokator handelt wäre eine Änderung hochgradig nichttrivial und würde alle Targets betreffen, also nicht nur AVR.

Mit C vs. C++ hat das überigens nichts zu tun. Die > 300 Passes nach dem Frontend sind für C und C++ die selben.

OP Persönliche Seite #7870012
Lesenswert?

Foka M. schrieb:

Ist es moeglich dem gcc-15.1 etwas schlankere Funktionsaufrufe beizubringen?

An den Funktionsaufrufen selbst liegt es ja nicht, es sei denn die Funktion(en) wurden gecloned.

Vielmehr scheint es um die Sicherung von Werten über Funktionsaufrufe hinweg zu gehen. Und da könnte -fno-caller-saves helfen.

avr-gcc (und also auch avr-g++) verwenden noch den alten lokalen Registerallokator. Das AVR Backend befindet sich noch in der Umstellung. Der neue Allokator ist noch nicht aktiviert; v15 verwendet noch den alten Allokator.

#7871252
Lesenswert?

Johann L. schrieb:

Vielmehr scheint es um die Sicherung von Werten über Funktionsaufrufe hinweg zu gehen. Und da könnte -fno-caller-saves helfen.

avr-gcc (und also auch avr-g++) verwenden noch den alten lokalen Registerallokator. Das AVR Backend befindet sich noch in der Umstellung. Der neue Allokator ist noch nicht aktiviert; v15 verwendet noch den alten Allokator.

Habe gerade -fno-caller-saves ausprobiert. Leider bringt es in meinem Fall nichts (keine Aenderung in der code-Groesse).

Aber es ist gut zu hoeren, dass es an der Stelle noch Potential vorhanden ist und der Registerallokator vielleicht noch optimiert wird.

-Foka

(Firma: ab) #7874551
Lesenswert?

avr-gcc 15.1.0 ist auf Godbolt.org für Experimente verfügbar. https://godbolt.org/z/YT4b93qM6

Auf https://blog.zakkemble.net/avr-gcc-builds/ ist ein Script zur Kom­pi­la­ti­on der Toolchain unter Linux downloadbar.

Die Links zu den aktuellen Quellen und Werkzeugen sind zu modifizieren. https://ftp.gnu.org/gnu/ ..

Eine Arbeitsversion der avr-libc findet sich unter https://github.com/avrdudes/avr-libc/blob/main/NEWS.md

Im Microchip Studio7 kann im "Solution Explorer | advanced | Link flavour configuration" die Toolchain für AVR 8-Bit cpp-language und AVR-8Bit c-language eingetragen und anschliessend für ein Projekt ausgewählt werden.

Im Anhang ein modifiziertes ZAK-Script.

Unter Linux Mint 22.1 Xia base: Ubuntu 24.04 noble:

Done in 3178 seconds - Toolchains are in /media/ab/Linux-HDD/avr-toolchain____/

Angehängte Dateien:
(Firma: @home) #7876340
Lesenswert?

Veit D. schrieb:

komisch, da fragt jemand nach Toolchains, bekommt alles auf dem Silbertablett und reagiert nicht einmal.

Vielen Dank für den Link/Silbertablett - funktioniert soweit, bis auf einen Bug der auch schon in v14 steckte, in v13 gibt es den Error nicht.

Ich bin gerade nicht Echtzeit fähig, mein Hund ist krank ...

Bug?!

1
const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"}; -> syntax error
2
const struct {char* copyright; char* calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"}; -> ok
Moderator Persönliche Seite #7876355
Lesenswert?

Apollo M. schrieb:

Bug?!

Der Bug ist aber in deinem Code.

Alle Compiler beschweren sich drüber:

1
$ gcc -O -Wall -Wextra -c bug.c
2
bug.c:1:71: warning: initialization of 'char' from 'char *' makes integer from pointer without a cast [-Wint-conversion]
3
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
4
      |                                                                       ^~~~~~~~~~~~~
5
bug.c:1:71: note: (near initialization for 'e3.calibration')
6
bug.c:1:71: error: initializer element is not computable at load time
7
bug.c:1:71: note: (near initialization for 'e3.calibration')
8
bug.c:1:14: warning: missing initializer for field 'calibration' of 'const struct <anonymous>' [-Wmissing-field-initializers]
9
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
10
      |              ^
11
bug.c:1:32: note: 'calibration' declared here
12
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
13
      |                                ^~~~~~~~~~~
14
$ cc -O -Wall -Wextra -c bug.c
15
bug.c:1:71: error: incompatible pointer to integer conversion initializing 'char' with an expression of type 'char[12]' [-Wint-conversion]
16
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
17
      |                                                                       ^~~~~~~~~~~~~
18
bug.c:1:71: error: initializer element is not a compile-time constant
19
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
20
      |                                                                       ^~~~~~~~~~~~~
21
2 errors generated.
22
$ clang19 -O -Wall -Wextra -c bug.c
23
bug.c:1:71: error: incompatible pointer to integer conversion initializing 'char' with an expression of type 'char[12]' [-Wint-conversion]
24
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
25
      |                                                                       ^~~~~~~~~~~~~
26
bug.c:1:71: error: initializer element is not a compile-time constant
27
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
28
      |                                                                       ^~~~~~~~~~~~~
29
2 errors generated.
30
$ clang15 -O -Wall -Wextra -c bug.c
31
bug.c:1:71: error: incompatible pointer to integer conversion initializing 'char' with an expression of type 'char[12]' [-Wint-conversion]
32
const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
33
                                                                      ^~~~~~~~~~~~~
34
bug.c:1:71: error: initializer element is not a compile-time constant
35
const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
36
                                                                      ^~~~~~~~~~~~~
37
2 errors generated.

Es hilft halt nichts, wenn du "char* foo" schreibst statt "char *foo" – der Stern, der aus "char" einen Zeiger "pointer to char" macht, gehört nicht zum Typ, sondern zum damit deklarierten "member".

Wenn du schreibst

1
const struct {char* copyright, *calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};

dann macht der Code das, was du dir vorstellst.

Offensichtlicher wäre es natürlich, auch den ersten Stern nach rechts zu rücken:

1
const struct {char *copyright, *calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};

Wenn du für den Zeiger lieber einen Typnamen hättest, dann:

1
typedef char * pchar;
2
const struct {pchar copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
#7876514
Lesenswert?

Jörg W. schrieb:

Es hilft halt nichts, wenn du "char* foo" schreibst statt "char *foo" – der Stern, der aus "char" einen Zeiger "pointer to char" macht, gehört nicht zum Typ, sondern zum damit deklarierten "member".

Naja, er ist Teil des Typs. Aber ja, in C war es ursprünglich so gedacht, dass er stattdessen auf der Seite des Namens steht, damit es der Dereferenzierung des Zeigers mehr ähnelt.

Offensichtlicher wäre es natürlich, auch den ersten Stern nach rechts zu rücken: const struct {char *copyright, *calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};

Oder einfach das Problem ganz zu umgehen, indem man die Members getrennt deklariert:

1
const struct {char* copyright; char* calibration;} e3 = {"LCQ V1.42 by 
2
XYZ","Calibration"};
#7876849
Lesenswert?

Apollo M. schrieb:

Bug?!

Nein.

1
> const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by 
2
> XYZ","Calibration"}; -> syntax error
3
> const struct {char* copyright; char* calibration;} e3 = {"LCQ V1.42 by 
4
> XYZ","Calibration"}; -> ok
5
>

Das ist das Problem wenn man denkt alle Variablen auf eine Zeile quetschen zu wollen um die Angabe vom Datentyp einsparen zu wollen.

Wenn man den fehlerhaften Syntax umformatiert in der Ansicht/Lesbarkeit, sieht man sehr schnell das etwas fehlt bzw. Komma/Semikolonfehler enthalten ist. Gerade beim Zeiger schlägt vermeintlich immer fehl, weil sich der "Stern" immer nur auf die erste Variable bezieht. Für die nachfolgende bleibt nur char übrig.

1
const struct {
2
  char* copyright,
3
  calibration;
4
} e3 = {
5
  "LCQ V1.42 by XYZ", "Calibration"
6
};

Das wäre vielleicht einleuchtender wie das gemeint ist, das für calibration nur char übrig bleibt. Wie gesagt, ich halte solche Einsparmaßnahmen grundlegend für unsinnig.

1
const struct {
2
  char *copyright,
3
  calibration;
4
} e3 = {
5
  "LCQ V1.42 by XYZ", "Calibration"
6
};

Deswegen bin ich kein Freund von vermeintlichen Abkürzungen. Außer ich habe gleichartige Funktionen o.ä, die in Tabellenform besser erkennbar sind. Den Datentyp spare ich nie ein.

#7876856
Lesenswert?

Veit D. schrieb:

Wenn man den fehlerhaften Syntax

<pedanterie> Syntax, die.

https://www.duden.de/rechtschreibung/Syntax https://de.wikipedia.org/wiki/Syntax </pedanterie>

Veit D. schrieb:

sieht man sehr schnell das etwas fehlt bzw. Komma/Semikolonfehler enthalten ist.

Der Fehler liegt hier in der Annahme, daß der * zum Typ und nicht zum Elementnamen gehört.

Mit einem Konstrukt à la

1
typedef char * pchar_t;
2

3
const struct {pchar_t copyright, calibration;} e3 = {"LCQ V1.42 by  XYZ","Calibration"};

ist der Fehler weg.

Schön ist das trotzdem nicht. Code "kompakt" schreiben zu wollen, spart zwar Textzeilen, macht aber exakt gar nichts übersichtlicher.

Bekommt man Geld zurück, wenn man weniger Zeichen für den Quelltext verbraucht?

Für den Compiler macht es exakt absolut überhaupt gar keinen Unterschied aus, wenn man statt des Krampfes da oben schreibt:

1
struct geraffel_t 
2
{
3
  char *copyright;
4
  char *calibration;
5
};
6

7
const struct geraffel_t e3 = 
8
{
9
  "LCQ V1.42 by  XYZ",
10
  "Calibration"
11
};

Oder gar

1
...
2

3
const struct geraffel_t e3 = 
4
{
5
  .copyright = "LCQ V1.42 by  XYZ",
6
  .calibration = "Calibration"
7
};
(Firma: @home) #7877078
Lesenswert?

Harald K. schrieb:

Der Fehler liegt hier in der Annahme, daß der * zum Typ und nicht zum Elementnamen gehört.

Jörg W. schrieb:

Wenn du schreibstconst struct {char* copyright, *calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"}; dann macht der Code das, was du dir vorstellst.

Offensichtlicher wäre es natürlich, auch den ersten Stern nach rechts zu rücken: const struct {char *copyright, *calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};

Das hat mich jetzt sehr überrascht und zu 99% (100% wenn das aus der aktuellen C Specification ableitbar bzw. stringent folgt) überzeugt. Hat irgendwer einen link dazu?

Ich war immer rechts orientiert ... und hatte jetzt angefangen davon abzugehen, weil ich irgendwo aufgeschnappt (und viele Quellen es auch praktisch so halten) sowie es auch logisch erscheint, dass char/int*/... ein daten type ist.

Die gcc Fehlermeldung ist dann auch verständlich und eindeutig. Also mache ich jetzt wieder eine Rolle rückwärts mit *rechts, weils der aktuelle Compiler es so will und hege 1% Zweifel ... allerdings wenn man beachtet, dass der * dereferenziert passt es, ABER in C gibt es mehrfach mehrfach Bedeutung von Token.

Daraus folgt, dass gcc v13.x (und davor) den Bug trägt, weil es da ohne Fehlermeldung zwei und nicht ein pointer und char sind.

Moderator Persönliche Seite #7877086
Lesenswert?

Apollo M. schrieb:

Daraus folgt, dass gcc v13.x (und davor) den Bug trägt, weil es da ohne Fehlermeldung zwei und nicht ein pointer und char sind.

Nö, war auch dort schon nicht anders:

1
$ gcc -v
2
Using built-in specs.
3
4
Thread model: posix
5
gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) 
6
$ gcc -c bug.c
7
bug.c:1:71: warning: initialization of ‘char’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion]
8
    1 | const struct {char* copyright, calibration;} e3 = {"LCQ V1.42 by XYZ","Calibration"};
9
      |                                                                       ^~~~~~~~~~~~~
10
bug.c:1:71: note: (near initialization for ‘e3.calibration’)
11
bug.c:1:71: error: initializer element is not computable at load time
12
bug.c:1:71: note: (near initialization for ‘e3.calibration’)
OP Persönliche Seite #7877103
Lesenswert?

Apollo M. schrieb:

Daraus folgt, dass gcc v13.x (und davor) den Bug trägt, weil es da ohne Fehlermeldung zwei und nicht ein pointer und char sind.

Kann ich nicht bestätogen. Eine adäquate Fehlermeldung (keine Warning) sehe ich mit GCC v3.4, v5.4, v8, v12, v13, v14, v15.

Damit der Code compiliert kann man als C++ übersetzen zusammen mit -fpermissive, also explizit kaputten[tm] Code erlauben:

Ohne -fpermissive:

1
$ echo 'const struct{char*copy,calib;}e3={"LCQ","Calib"};' | avr-g++ -xc++ - -fsyntax-only
2
<stdin>:1:35: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
3
<stdin>:1:41: error: invalid conversion from 'const char*' to 'char' [-fpermissive]

Mit -fpermissive:

1
$ echo 'const struct{char*copy,calib;}e3={"LCQ","Calib"};' | avr-g++ -xc++ - -fsyntax-only -fpermissive
2
<stdin>:1:35: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
3
<stdin>:1:41: warning: invalid conversion from 'const char*' to 'char' [-fpermissive]
#7877158
Lesenswert?

Apollo M. schrieb:

Veit D. schrieb:

Wie gesagt, ich halte solche Einsparmaßnahmen grundlegend für unsinnig.

Widerspruch, weil denkbar eine Frage von persönlicher Perspektive ... weitere Beispiele zum diskutieren :-)

1
> //der ersten Variante gebe ich den Vorzug
2
> while (1) continue; while (1); while (1) {};
3
> while (x=y,x); while (x=y); x=y; while (x)
4
>

Das kann man so schreiben wenn es sonst niemand liest. :-) Es wird auch für dich Jahre später schwer lesbar sein.

Verstehe mich nicht falsch. Du kannst schreiben wie du das möchtest. Nur wenn der Compiler meckert, spätestens dann sollte man seine Zeilen überprüfen.

Ein Bjarne Stroustrup und Ulrich Breymann schreiben in ihren Büchern auch

1
int* ip

und nicht "durchgehend"

1
int *ip

Obwohl U. Breymann in seinem Text dazu folgendes richtig beschreibt.

1
Die Variable ip ist vom Typ »Zeiger auf int«. Der Stern * bezieht sich also nur auf den direkt folgenden Namen.

Und paar Zeilen darüber auf gleicher Seite schreibt er es in der Form

1
int *ip {&i}

Das heißt wie schon gesagt bei Schreibweisen mit Mehrfachaufzählung wie

1
int* ip, mac

wird es gefährlich, weil mac kein Zeiger mehr hat, sondern nur den Datentyp int.

Wenn man jeder Deklaration eine eigene Zeile gönnt, dann ist es praktisch egal wie man es schreibt. Dann ist es immer sofort ersichtlich.

#7877214
Lesenswert?

Apollo M. schrieb:

Daraus folgt, dass gcc v13.x (und davor) den Bug trägt, weil es da ohne Fehlermeldung zwei und nicht ein pointer und char sind.

Was ich dazu noch sagen möchte. Unabhängig davon ob das bei dir kompilierte und nun nicht mehr o.ä. Generell wird jede neue Compilerversion strenger. Wirft also mehr Warnungen/Fehler wie die Version davor. Das sollte man dankbar aufnehmen um Probleme im Code zu erkennen um damit schwerwiegende Fehler im Vorfeld vermeiden zu können. Siehe die Fehlermeldung also nicht als Bug sondern als Hilfe.

OP Persönliche Seite #7877265
Lesenswert?

Apollo M. schrieb:

Harald K. schrieb:

Ganz simpler Test:

Überzeugt trotzdem und Grund genug die 1% Zweifel jetzt an der Garderobe abzugeben!

Ein Test ersetzt aber keine Spezifikation.

Im C99 Standard: Im Abschnitt 6.7.5 Declarators ist der Aufbau von Deklaratoren beschrieben, woraus sich die Semantik der diskutierten Deklaration ergibt. Das ganze ist im Stil einer kontextfreien Grammatik formuliert, damit alle möglichen Fälle (das sind unendlich viele) abgedeckt sind.

OP Persönliche Seite #7877921
Lesenswert?

Foka M. schrieb:

Habe gerade paar meiner Projekte damit und aktueller avr-libc (git) durchgebaut. Generierter code scheint, bei mir, mit dem gcc-15.1 deutlich kleiner zu sein als gcc-14.2. An gcc-13.1 kommt er allerdings nicht heran.

Ein Grund könnte der alte lokale Register-Allokator sein (Reload). GCC hat 2 solcher lokaler Allokatoren, und das alte Reload ist bei fast allen Targets schon durch das neue LRA ersetzt -- nicht aber für AVR

https://gcc.gnu.org/PR113934

weil es noch einen Fall gibt, wo LRA falschen Code erzeugt:

https://gcc.gnu.org/PR118591

Aus diesem Grunde ist -mlra im avr-gxx noch deaktiviert (und nicht dokumentiert, weil die Option ja spätestens mit Entfernung von Reload wieder entfällt).

Hier ein Beispiel, wo die Codegröße von v13 zu v15 ansteigt. (Reload wird natürlich nicht mehr supprted, zumindest nicht was die Qualität des erzeugten Codes angeht.)

1
typedef __SIZE_TYPE__ size_t;
2
extern size_t strlen (const char*) __attribute__((__pure__));
3
extern int strncmp (const char*, const char*, size_t) __attribute__((__pure__));
4
extern int atoi (const char*);
5

6
static inline _Bool is_prefix (const char *pre, const char *s)
7
{
8
    return 0 == strncmp (pre, s, strlen (pre));
9
}
10

11
_Bool get_int (const char *arg, const char *prefix, int *pi)
12
{
13
    if (! is_prefix (prefix, arg))
14
        return 0;
15
    *pi = atoi (arg + strlen (prefix));
16
    return 1;
17
}

Mit avr-gcc v15 -mno-lra wird mehr Stack gebraucht und sogar ein Frame angelegt:

1
$ avr-gcc-8 getint.c -Os -S -mmcu=atmega8 && grep 'size =' getint.s
2
/* frame size = 0 */
3
/* stack size = 6 */
4
$ avr-gcc-13 getint.c -Os -S -mmcu=atmega8 && grep 'size =' getint.s
5
/* frame size = 0 */
6
/* stack size = 6 */
7
$ avr-gcc-15 getint.c -Os -S -mmcu=atmega8 && grep 'size =' getint.s
8
/* frame size = 4 */
9
/* stack size = 8 */
10
$ avr-gcc-15 getint.c -Os -S -mmcu=atmega8 -mlra && grep 'size =' getint.s
11
/* frame size = 0 */
12
/* stack size = 6 */

Das schlägt natürlich durch auf die Codegröße:

1
$ avr-gcc-8 getint.c -Os -c -mmcu=atmega8 && avr-size getint.o
2
   text     data      bss      dec      hex  filename
3
     76        0        0       76       4c  getint.o
4
$ avr-gcc-13 getint.c -Os -c -mmcu=atmega8 && avr-size getint.o
5
   text     data      bss      dec      hex  filename
6
     76        0        0       76       4c  getint.o
7
$ avr-gcc-15 getint.c -Os -c -mmcu=atmega8 && avr-size getint.o
8
   text     data      bss      dec      hex  filename
9
     94        0        0       94       5e  getint.o
10
$ avr-gcc-15 getint.c -Os -c -mmcu=atmega8 -mlra && avr-size getint.o
11
   text     data      bss      dec      hex  filename
12
     76        0        0       76       4c  getint.o
#7894794
Lesenswert?

Hallo,

wegen erzeugter Codegröße. Wird von Fall zu Fall abhängen. Mein Programm für die Modelleisenbahn kompiliert zu ...

1
avr-gcc / Flash  / RAM
2
12.3.0  / 37.468 / 5.078 (Bytes)
3
13.3.0  / 36.550 / 5.078 (Bytes)
4
14.3.0  / 36.935 / 3.292 (Bytes)
5
15.1.0  / 36.769 / 3.292 (Bytes)

Ab 14.x merkt man den Effekt das Konstanten automatisch im Flash landen. µC AVR128DB64.

#7906848
Lesenswert?

Uwe D. schrieb:

Johann L. schrieb:

Da oktal in MISRA absolut verboten ist, darf man also immer noch nicht "x = 0;" schreiben sondern muss weiterhin "x = 1-1;" o.ä.

Witzig, stimmt aber nicht ganz. x=0 ist in MISRA natürlich erlaubt. (Für alle, die Schnappatmung bekommen haben... :-) )

Auszug: MISRA C:2012 Rule 7.1 Octal constants shall not be used

Rationale: Octal constants are denoted by a leading zero. Developers can mistake an octal constant as a decimal constant with a redundant leading zero.

Wichtig: "leading zero", eine 0 alleine ist also keine octal Zahl.

So ist es IMHO im C Standard auch definiert.

1
x = 0;  // compliant
2
x = 00;     // not compliant        
3
x = 01;     // not compliant
OP Persönliche Seite #7928269
Lesenswert?

Irgendwann demnächst ist ja auch eine neue Release der AVR-LibC geplant.

NEWS: https://github.com/avrdudes/avr-libc/blob/main/NEWS.md

HTML Dokumentation (Vorschau): https://avrdudes.github.io/avr-libc/avr-libc-user-manual-2.3.0/index.html

Noch ist Zeit zum Meckern :-)

p.s.: Die Web-Links in NEWS führen noch zur /aktuellen/ Dokumentation, reflektieren also noch nicht die Änderunden in der v2.3. Für Doku zur v2.3 einfach der obigen HTML Vorschau folgen.

: Bearbeitet durch User
OP Persönliche Seite #8045332
Lesenswert?

Die diesjährige GCC Release v16 ist raus: https://gcc.gnu.org/pipermail/gcc/2026-April/248065.html https://gcc.gnu.org/gcc-16/changes.html

Im Gegensatz zur v15, wo es einige Verbesserungen und Erweiterungen für AVR gab, hat die v16 praktisch keine AVR-spezifischen Änderungen. Lediglich der Code für Shifts mit konstantem Offset wurde leicht verbessert. Beispiel:

1
#include <stdint.h>
2

3
uint32_t lsr22 (uint32_t x)
4
{
5
    return x >> 22;
6
}

Mit -Os für ATmega8:

v14

1
    ldi r18,22
2
1:  lsr r25
3
    ror r24
4
    ror r23
5
    ror r22
6
    dec r18
7
    brne 1b

v15

1
    movw r22,r24
2
    ldi r18,6
3
1:  lsr r23
4
    ror r22
5
    dec r18
6
    brne 1b
7
    ldi r24,0
8
    ldi r25,0

v16

1
    movw r22,r24
2
    andi r22,-64
3
    ori r22,32
4
1:  lsr r23
5
    ror r22
6
    brcc 1b
7
    ldi r24,0
8
    ldi r25,0

Das Thema KI geht natürlich auch an FOSS nicht vorbei, und in den GCC Mailing Listen gibt es mehrere Threads zum Thema:

Policy on use of LLM tools and bug fixes

https://gcc.gnu.org/pipermail/gcc/2026-March/247679.html

GCC Development AI Policy Working Group Led by Jonathan Wakely

https://gcc.gnu.org/pipermail/gcc/2026-April/248017.html

Dabei geht es um den Einsatz von KI-Tools durch Entwickler, und nicht etwa um KI in den Tools selbst.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren