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_code
eine 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