Wie füge ich eine eingebaute Funktion in einem GCC-Plugin hinzu?

Lesezeit: 5 Minuten

Eugenes Benutzeravatar
Eugen

Ist es möglich, dass ein GCC-Plugin eine neue eingebaute Funktion hinzufügt? Wenn ja, wie macht man es richtig?

GCC-Version ist 5.3 (oder neuer). Der Code wird von dem in C geschriebenen Plugin kompiliert und verarbeitet.

Es wird in der erwähnt Begründung für GCC-Plugins auf gcc-melt.org dass dies machbar ist, aber ich kann nicht sehen, wie.

Soweit ich in den Quellen von GCC sehen kann, werden die Builtins mit erstellt add_builtin_function() aus gcc/langhooks.c:

tree
add_builtin_function (const char *name,
      tree type,
      int function_code,
      enum built_in_class cl,
      const char *library_name,
      tree attrs)

Es ist mehr oder weniger klar, welche Werte die Argumente dieser Funktion haben sollten, außer für function_codeeine eindeutige numerische ID der Funktion.

Sieht aus wie (vgl add_builtin_function_common()), ein Wert von enum built_in_function wird dort erwartet, aber ein GCC-Plugin kann diese Aufzählung nicht ändern.

Es kann kein zufälliger Wert größer als übergeben werden END_BUILTINS wie function_code auch nicht, so scheint es. builtin_decl_implicit() und builtin_decl_explicit() hätte in diesem Fall eine fehlgeschlagene Behauptung.

Was ist also der richtige Weg, um ein integriertes GCC-Plugin hinzuzufügen (ohne MELT und dergleichen zu verwenden, nur die GCC-Plugin-API)?

Aktualisieren
Ich habe mir nochmal die Umsetzung angeschaut add_builtin_function_common() und von langhooks.builtin_function() für C sowie wie diese in GCC verwendet werden. Es scheint, dass 0 als akzeptabel ist function_code in manchen Fällen. Sie können nicht verwenden builtin_decl_implicit() dann kannst du aber die von DECL zurückgesendete speichern add_builtin_function() und später verwenden.

Anscheinend ist das einzige Ereignis, bei dem ich versuchen kann, integrierte Funktionen auf diese Weise zu erstellen, PLUGIN_START_UNIT (andernfalls kann GCC aufgrund von abstürzen external_scope Variable ist NULL).

Ich habe in dieser Phase Folgendes versucht (fntype wurde zuvor erstellt):

decl = add_builtin_function (
    "my_helper", fntype,
    0 /* function_code */,
    BUILT_IN_NORMAL /* enum built_in_class cl */,
    NULL /* library_name */,
    NULL_TREE /* attrs */)

my_helper wurde in einer anderen C-Quelldatei definiert, die mit der Hauptquelldatei kompiliert und verknüpft wurde. Dann habe ich decl verwendet, um die Aufrufe dieser Funktion in andere Funktionen einzufügen (gimple_build_call) während meines GIMPLE-Passes.

GCC gab keine Fehler aus und fügte den Aufruf tatsächlich ein my_helper sondern als Aufruf einer gewöhnlichen Funktion. Ich brauchte eigentlich ein Builtin, um einen Aufruf zu vermeiden, sondern den Körper der Funktion einzufügen.

Auf der anderen Seite, tsan0 pass, das direkt nach my pass ausgeführt wird, fügt die Aufrufe eingebauter Funktionen ein, genau wie man es erwarten würde: Es gibt keinen expliziten Aufruf als Ergebnis, nur der Hauptteil der Funktion wird eingefügt. Seine Builtins werden jedoch von GCC selbst und nicht von den Plugins definiert.

Also nehme ich an, dass mein Built-In noch etwas braucht, um ein gültiges Built-In zu sein, aber ich weiß nicht, was es ist. Was könnte das sein?

  • Muss die Funktion wirklich ein builtin im Sinne von gcc sein? Könnte es nicht eine reguläre Funktion sein?

    – Marc Glisse

    13. September 2016 um 19:32 Uhr

  • Für das Problem, das ich eigentlich zu lösen versuche (beschrieben hier detaillierter), es muss nicht per se ein GCC builtin sein. Was ich dort brauche, ist eine Möglichkeit, den Code einer C-Funktion in den Code einer anderen einzufügen, ohne die erstere tatsächlich aufzurufen. Builtins und Inlines sind offensichtliche Möglichkeiten, aber ich habe bisher kein Glück mit beiden. Was diese spezielle Frage betrifft – ja, ich bin nur neugierig auf die Einbauten. Einige sagen, dass es möglich ist, Builtins über ein GCC-Plugin hinzuzufügen, aber ich kann nicht sehen, wie.

    – Eugen

    14. September 2016 um 9:15 Uhr


  • @Nisarg: Ich habe den formatierungsbezogenen Teil Ihrer Bearbeitung angewendet, danke. Was den letzten Satz betrifft – nein, ich wollte nicht fragen, was Sie vorgeschlagen haben. Ich habe es jetzt ersetzt, um die Dinge klarer zu machen.

    – Eugen

    12. September 2018 um 19:27 Uhr

  • Hast du es versucht __attribute__((always_inline))?

    – minmaxavg

    19. September 2018 um 5:33 Uhr

  • Fürs Protokoll: Am Ende habe ich eine einfache Übersetzung aus einer Folge von C-ähnlichen Funktionsaufrufen in GIMPLE-Sequenzen implementiert, um dieses Problem teilweise zu umgehen. Das GCC-Plugin fügt diese GIMPLE-Sequenzen bei Bedarf ein. Es kann die Aufrufe von Helfern, die es einfügt, nicht “inlinen”, aber es reicht mir im Moment aus. Die Einzelheiten sind in diesem Commitsiehe die Änderungen an i13n/ Unterverzeichnis Funktioniert für mich, aber die eingebauten Helfer könnten natürlich besser sein.

    – Eugen

    19. September 2018 um 13:38 Uhr


Ich gehe davon aus, dass Sie (aus Ihrem Kommentar und dem verlinkten Beitrag) C-Code in eine Funktion einfügen möchten. In diesem Fall hätte ich gedacht, dass Sie nicht so weit gehen müssten, ein Compiler-Plugin zu schreiben. Schau mal rein Boost.Präprozessordas sehr fortgeschrittene Manipulationen von C-Code nur mit dem Präprozessor durchführen kann.

  • Ich wollte die neuen Builtins im Kernel-Code verwenden, also nur für die C-Sprache. Ich habe einige Erfahrung mit Boost und würde es hier lieber vermeiden. Andererseits werden GCC-Plugins schon seit einiger Zeit vom Linux-Kernel unterstützt und könnten hier wohl zum Einsatz kommen.

    – Eugen

    29. Juli 2020 um 19:56 Uhr

  • Preprocessor ist eine Nur-Header-Bibliothek, die mit C funktioniert und kein C++ erfordert. Ich sehe keinen Grund, warum es im Kernel nicht funktionieren sollte.

    – Ari Fordsham

    30. Juli 2020 um 17:03 Uhr

  • Nun, man weiß nie, bis sie es versuchen 😉 Wie auch immer, wie ich in den Kommentaren zu der Frage sagte, habe ich bereits eine Problemumgehung vorbereitet und sie hat 2016 gut funktioniert, als sie benötigt wurde. Ich wollte nur wissen, vielleicht könnte jemand auf einen korrekten Weg hinweisen, um dort Builtins zu erstellen.

    – Eugen

    31. Juli 2020 um 7:37 Uhr

1414760cookie-checkWie füge ich eine eingebaute Funktion in einem GCC-Plugin hinzu?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy