www.mikrocontroller.net

Forum: Compiler & IDEs Mehrere Quelldateien, inline und __attribute__((always_inline))


Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!

Ich habe ein Problem eine inline-Funktion aufzurufen und dabei das 
Inlining zu erzwingen. Folgendes Beispiel sollte das Problem 
reproduzieren:

// header.h

inline void bar(void) __attribute__((always_inline));

// ...
// A.c

#include "header.h"

void
foo()
{
  bar();
}
// B.c

#include "header.h"

inline void
bar(void)
{
  // Do something.
}

// ...

Der GCC bricht das Kompilieren mit

bfin-elf-gcc -I./include/ -g -mcpu=bf537 -std=gnu99 -Wall -pedantic -Os -save-temps -Winline   -c -o A.o A.c
events.c: In Funktion »foo«:
./include/header.h:129: nicht implementiert: »inline« beim Aufruf von »bar« gescheitert: function body not available
A.c:90: nicht implementiert: von hier aufgerufen

Scheint also als ob inline nicht geht weil er das Objekt nicht greifen 
kann?! Also Kontrolle indem alles in eine Quelldatei kommt:

// header.h

inline void bar(void) __attribute__((always_inline));

// ...
// A.c

#include "header.h"

void
foo()
{
  bar();
}

inline void
bar(void)
{
  // Do something.
}

Et voila, er kompiliert durch, ein Blick ins ASM-Listing bestätigt das 
ordnungsgemäße Inlinen (BTW: Jedoch nicht bei abgeschalteter 
Optimierung, was imho nicht zur Aussage in der Doku passt).

Nochwas am Rande. Wenn ich das __attribute__((always_inline)) entferne 
meckert er:

bfin-elf-gcc -I./include/ -g -mcpu=bf537 -std=gnu99 -Wall -pedantic -Os -save-temps -Winline   -c -o events.o events.c
A.c: In Funktion »foo«:
A.c:147: Warnung: »inline« beim Aufruf von »bar« gescheitert: --param max-inline-insns-single limit reached
A.c:90: Warnung: von hier aufgerufen

Wie bekomme ich aber den GCC dazu das über Quelldateigrenzen hinweg zu 
realisieren? Liegt es vllt am gnu99-Schalter - die Doku ist etwas knapp?

Cheers
TH

Edit: gcc-Version 4.1.2 (ADI svn)

Autor: Μαtthias W. (matthias) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

AFAIK geht das nicht. Wie soll der Compiler die Funktion "inlinen" 
können wenn er die Größe eben selbiger nicht kennt? Du mußt die Funktion 
direkt im Header (als static inline) implementieren. Dann solltest du 
den gewünschten Effekt erreichen.

Matthias

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Scheint also als ob inline nicht geht weil er das Objekt nicht greifen
> kann?!

Es ist zwar richtig, daß er das Objekt nicht "greifen" kann, aber das 
würde ihm auch nichts bringen. Er braucht auch den Quellcode.


> Wie bekomme ich aber den GCC dazu das über Quelldateigrenzen hinweg zu
> realisieren?

Gar nicht. Um eine Funktion inlinen zu können, braucht der Compiler 
natürlich deren Quelltext. Also muß die Implementation an der Stelle, wo 
die Funktion aufgerufen wird, bekannt sein durch vorherige Definition in 
derselben Quelldatei oder einem inkludierten Header.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Inline-Funktion erzeugt wie ein Define den Code erst beim Aufruf.
Sie gehört also wie ein Define ins h-File.

Der Unterschied zum Define ist nur die strengere Typ-Prüfung.


Peter

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:

> Der Unterschied zum Define ist nur die strengere Typ-Prüfung.

<nitpickmode>
Es gibt noch mehr Unterschiede, beispielsweise die Möglichkeit, einen
Wert aus der Funktion zurück zu geben und trotzdem auch lokale
Variablen innerhalb der Funktion zur Verfügung zu haben (die oftmals
das Formulieren vereinfachen).  Zwar kann GCC auch einen braced block
als rechte Seite eines Ausdrucks benutzen (und daraus gewissermaßen
einen Wert zurück geben), aber das ist im Gegensatz zur Inline-Funktion
kein Standard-C.
</nitpickmode>

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:
> Eine Inline-Funktion erzeugt wie ein Define den Code erst beim Aufruf.
> Sie gehört also wie ein Define ins h-File.
>
> Der Unterschied zum Define ist nur die strengere Typ-Prüfung.

Nicht ganz, ein Define ist reiner Textersatz (geschieht also im 
Präprozessor, nicht im Compiler) während Inlining innerhalb des 
Compilers umgesetzt wird. Etwa ist es nicht egal, ob bei foo(++x) foo 
als Makro oder als Inline-Funktion zur Verfügung gestellt wird.

@pumpkin

Zunächst ist es ungewohnt, den Quellcode in nen Header zu schreiben. 
Aber das ist das Vorgehen bei static inline.

Die Alternative wäre extern inline, was aber wohl nicht das leistet, was 
du willst: Im C-Modul, wo die so gekennzeichnete Funktion implementiert 
wird, wird sie (wenn möglich) geinlint, der Compiler erzeugt aber 
zusätzlich eine Implementierung der Funktion, falls sie von extern 
referenziert wird. Dazu muss ja eine Implementierung vorliegen. In dem 
Fall hätte man die Funktion zwar in nem C-Modul, aber nichts gewonnen. 
In anderen Modulen könnte sie nicht geinlint werden, und im 
implementierenden Modul wird sie vermutlich nicht gerufen.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin moin!

Also wie gedacht, er braucht den Code. Es ist allerdings schade, dass es 
da keinen Mechanismus (evtl. in Kombination mit dem Linker?) gibt der 
das ermöglicht.

Aber danke für die Kommentare!

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
T. H. wrote:
> Es ist allerdings schade, dass es da keinen Mechanismus (evtl. in
> Kombination mit dem Linker?) gibt der das ermöglicht.

Gibt es. Wird beispielsweise beim ARM linker "branch inlining" genannt. 
Das kann allerdings nur im Einzelfall funktionieren. Der Linker kann ja 
nicht einfach eine beliebig große Einfügung vornehmen. Beim ARM Linker 
ist diese Funktion daher auf Unterprogramme beschränkt, die nicht mehr 
Platz beanspruchen, als der Unterprogrammaufruf selbst (ein Wort, also 
maximal zwei Befehle).

Gruß
Marcus
http://www.doulos.com/arm/

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.