Wie lautet der richtige Aufruf einer Win32 / 64-Funktion von LLVM?

9

Ich versuche, eine Methode von LLVM IR zurück zu C ++ - Code aufzurufen. Ich arbeite in 64-Bit Visual C ++, oder wie LLVM es beschreibt:

%Vor%

Bei Integer-Typen und Zeigertypen funktioniert mein Code so, wie er ist. Gleitkommazahlen scheinen jedoch etwas seltsam zu sein.

Grundsätzlich sieht der Anruf so aus:

%Vor%

und LLVM IR sieht so aus:

%Vor%

Ich dachte, dass das Problem wahrscheinlich in der Art und Weise liegt, wie die Aufrufkonventionen funktionieren. Also habe ich versucht, einige Anpassungen vorzunehmen, um das zu korrigieren:

%Vor%

Leider, egal was ich versuche, habe ich am Ende "invalid instruction" -Fehler, die dieser Benutzer als ein Problem mit Aufrufkonventionen angibt: Clang produziert ausführbare Datei mit illegalem Befehl . Ich habe dies mit X86-64_Win64, Stdcall, Fastcall und keine Aufruf Konvention Spezifikationen versucht - alle mit dem gleichen Ergebnis.

Ich habe Ссылка gelesen, um herauszufinden, was hier vor sich geht. Dann schaute ich auf die Assembly-Ausgabe, die von LLVM generiert werden soll (mit dem API-Aufruf targetMachine- & gt; addPassesToEmitFile) und fand:

%Vor%

Laut MSDN sollte Argument 2 in% xmm1 angegeben werden, was ebenfalls korrekt zu sein scheint. Wenn jedoch überprüft wird, ob alles im Debugger funktioniert, meldet Visual Studio viele Fragezeichen (z. B. "illegaler Befehl").

Jede Rückmeldung ist willkommen.

Der Demontagecode:

%Vor%

Einige Informationen über den Speicher fehlen. Speicheransicht:

0x00000144F248001B 48 b8 c0 48 b8 c8 fa 7f 00 00 48 b9 00 00 47 f2 44 01 00 00 62 f1 ff 08 10 09 48 8b 4c 24 20 ff d0 31 c0 48 83 c4 28 c3 00 00 00 00 00. ..

Die Fragezeichen, die hier fehlen, sind: '62 f1 '.

Irgendein Code ist hilfreich, um zu sehen, wie ich das JIT kompiliere usw. Ich fürchte, es ist ein bisschen lang, aber hilft, die Idee zu bekommen ... und ich habe keine Ahnung, wie man ein kleineres Stück Code erstellt.

%Vor%

Aktualisieren (Fortschritt)

Anscheinend hat mein Skylake Probleme mit der vmovsd-Anweisung. Wenn derselbe Code auf einem Haswell (Server) ausgeführt wird, ist der Test erfolgreich. Ich habe die Assemblyausgabe auf beiden überprüft - sie sind genau gleich.

Nur um sicher zu sein: XSAVE / XRESTORE sollte nicht das Problem auf Win10-x64 sein, aber lasst uns trotzdem herausfinden. Ich habe die Features mit dem Code von Ссылка und dem XSAVE / XRESTORE von Ссылка . Letzteres läuft gut. Was die ersten betrifft, sind dies die Ergebnisse:

%Vor%

Es ist seltsam, also dachte ich mir: Warum nicht einfach die Anweisung direkt ausgeben?

%Vor%

Dieser Code läuft einwandfrei. Die Demontage:

%Vor%

Offensichtlich wird es das Register xmm1 nicht verwenden, aber es beweist immer noch, dass der Befehl selbst den Trick macht.

    
atlaste 25.08.2016, 15:46
quelle

1 Antwort

4

Ich habe gerade bei einem anderen Intel Haswell nachgesehen, was hier vor sich geht, und folgendes gefunden:

%Vor%

Offenbar gibt es bei Intel Haswell einen weiteren Byte-Code-Befehl als auf meinem Skylake.

@Ha. Eigentlich war es so freundlich, mir hier in die richtige Richtung zu zeigen. Ja, die versteckten Bytes zeigen tatsächlich VMOVSD an, aber anscheinend ist es als EVEX codiert. Das ist alles schön und gut, aber EVEX Präfix / Codierung wird in der neuesten Skylake-Architektur als Teil von AVX512 eingeführt werden, die bis Skylake Purley 2017 nicht unterstützt werden. Mit anderen Worten, das ist ungültige Anweisung.

Um zu überprüfen, habe ich einen Haltepunkt in X86MCCodeEmitter::EmitMemModRMByte gesetzt. Irgendwann sehe ich, dass bool HasEVEX = [...] auf wahr auswertet. Dies bestätigt, dass der Codegen / Emitter die falsche Ausgabe erzeugt.

Meine Schlussfolgerung ist daher, dass dies ein Fehler in der Zielinformation von LLVM für Skylake CPUs sein muss. Das bedeutet, dass es nur noch zwei Dinge zu tun gibt: Finde heraus, wo genau dieser Fehler in LLVM ist, damit wir das Problem lösen und den Fehler dem LLVM-Team melden können ...

Also wo ist es in LLVM? Das ist schwer zu sagen ... x86.td.def definiert skylake-Funktionen als 'FeatureAVX512', die wahrscheinlich X86SSELevel zu AVX512F auslösen werden. Das wiederum wird falsche Anweisungen geben. Als Workaround ist es am besten, LLVM einfach mitzuteilen, dass wir stattdessen einen Intel Haswell haben, und alles wird gut:

%Vor%

Test, funktioniert.

    
atlaste 28.08.2016, 10:21
quelle