2015-01-21 8 views
19

Die IdeeMit GHC API Haskell Quellen zu Core- und Core auf binäre

Hallo zu kompilieren! Ich möchte ein Programm erstellen, das Haskell Core generiert und GHC API verwendet, um es weiter in eine ausführbare Datei zu kompilieren. Aber bevor ich es mache, möchte ich ein sehr einfaches Beispiel konstruieren, das zeigt, wie wir Haskell-Quellen einfach in CORE und dann in die Binärdatei kompilieren können.

Das Problem

Ich habe eine Menge von Dokumentation und versucht, viele Methoden von GHC Api, aber jetzt ohne Erfolg lesen. Ich habe mit Official GHC Api introduction begonnen und die Beispiele erfolgreich zusammengestellt. Die Beispiele zeigen die Verwendung der folgenden Funktionen: parseModule, typecheckModule, desugarModule, getNamesInScope und getModuleGraph, deckt jedoch nicht den abschließenden Kompilierungsschritt ab. Auf der anderen Seite gibt es einige Funktionen in der API, deren Namen auf das Problem bezogen sind, wie HscMain.{hscCompileOneShot, hscCompileBatch} oder GHC.{compileToCoreModule, compileCoreToObj}. Ich habe versucht, sie zu benutzen, aber ich bekomme Laufzeitfehler, wie in diesem Beispiel:

import GHC 
import GHC.Paths (libdir) 
import DynFlags 
targetFile = "Test.hs" 

main :: IO() 
main = do 
    res <- example 
    return() 

example = 
    defaultErrorHandler defaultFatalMessager defaultFlushOut $ do 
     runGhc (Just libdir) $ do 
     dflags <- getSessionDynFlags 
     let dflags' = foldl xopt_set dflags 
          [Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash] 
     setSessionDynFlags dflags' 
     coreMod <- compileToCoreModule targetFile 
     compileCoreToObj False coreMod "foo" "bar" 
     return() 

, die mit ghc -package ghc Main.hs zusammengestellt werden können und die Ergebnisse in der folgenden Fehler während der Laufzeit:

Main: panic! (the 'impossible' happened) 
    (GHC version 7.8.3 for x86_64-unknown-linux): 
    expectJust mkStubPaths 

die natürlich kann das Ergebnis einer falschen API-Verwendung sein, insbesondere wegen der Zeile compileCoreToObj False coreMod "foo" "bar", wenn die Zeichenfolge nur zufällige Zeichen sind, weil die Dokumentation nicht viel über sie aussagt. Wenn wir in die Quellen schauen, scheint es, dass der erste der Name der Ausgabe ist und der zweite "extCore_filename" ist, was auch immer es sein könnte.

Eine weitere beunruhigende Sache ist der Kommentar in der Dokumentation neben die compileCoreToObj Funktion:

[...] Das hat bisher nur mit einem einzigen eigenständigen Modul getestet.

Aber ich hoffe, es wird keine weiteren Probleme einführen.

Die Frage

Was ist die beste Art und Weise, diese Lösung zu schaffen? Wie können wir ein minimales Arbeitsbeispiel erstellen, das Haskell-Quellen lädt, sie in das CORE kompiliert und dann den Kern zur finalen ausführbaren Datei kompiliert (unter Verwendung der GHC-API). Der Zwischenschritt wird für das weitere Ersetzen durch benutzerdefiniertes CORE benötigt.

Als Neben Frage - ist es derzeit möglich GHC mit externen Core-Dateien zur Verfügung zu stellen oder diese Funktion ist noch nicht implementiert, und ich werde den Core manuell konstruieren muß, mit GHC.Api (bezogen auf: Compiling to GHC Core)

aktualisiert

konnte ich endlich ein kleines Beispiel erstellen ermöglicht ein Modul zu laden und es zu .hi und .o Dateien zu kompilieren.Dies ist keine Lösung für das Problem, weil es nicht erlaubt, mich um den Kern zu ersetzen und es keine Verknüpfung die Objektdateien in ausführbaren Dateien noch:

import GHC 
import GHC.Paths (libdir) 
import DynFlags 
import Linker 
import Module 
targetFile = "Test.hs" 

main :: IO() 
main = do 
    res <- example 
    return() 

example = 
    defaultErrorHandler defaultFatalMessager defaultFlushOut $ do 
     runGhc (Just libdir) $ do 
     dflags <- getSessionDynFlags 
     let dflags2 = dflags { ghcLink = LinkBinary 
          , hscTarget = HscAsm 
          } 
     let dflags' = foldl xopt_set dflags2 
          [Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash] 
     setSessionDynFlags dflags' 
     setTargets =<< sequence [guessTarget "Test.hs" Nothing] 

     load LoadAllTargets 
     return() 
+0

Die Entwickler der [ghc-Mailingliste] (https://www.haskell.org/mailman/listinfo/ghc-devs) sind wahrscheinlich diejenigen, die die Antworten haben, nach denen Sie suchen. – gxtaillon

+1

Ich glaube, dass in letzter Zeit Arbeit geleistet wurde, Plugins Kern-zu-Kern-Umwandlungen innerhalb der GHC-Pipeline zu ermöglichen. nicht genau das, was du willst. Vielleicht könnten Sie kurz erklären, warum Sie diesen präzisen Arbeitsablauf durchführen möchten. –

+1

@ChristianConkle Ich möchte nicht 'CORE -> CORE' Plugin. Ich erstelle meine eigene Sprache und möchte sie zum Kern kompilieren und dann GHC-Pipeline verwenden. Entschuldigung für Unklarheiten. –

Antwort

-2

Kurze Antwort: Sobald Sie Datei, die Sie das verwenden, um das Objekt haben c Compiler Ihrer Wahl, um einen Haupt-Stub zu kompilieren und in eine ausführbare Datei zu verlinken.

Wenn Sie die Objektdatei haben, dann sind die letzten Schritte, die GHC tun würde, im Linker und einem C-Compiler gemacht. Zum Beispiel durch die -verbose Flagge und -keep-tmp-Dateien für eine einfache hello_world Einstellung, die letzten drei Schritte für mich, nachdem die Objekte bauen, waren:

'/usr/bin/gcc' '-fno-stack-protector' '-Wl,--hash-size=31' '-Wl,--reduce-memory-overheads' '-c' '/tmp/ghc29076_0/ghc29076_0.c' '-o' '/tmp/ghc29076_0/ghc29076_0.o' '-DTABLES_NEXT_TO_CODE' '-I/usr/lib/ghc/include' 
*** C Compiler: 
'/usr/bin/gcc' '-fno-stack-protector' '-Wl,--hash-size=31' '-Wl,--reduce-memory-overheads' '-c' '/tmp/ghc29076_0/ghc29076_0.s' '-o' '/tmp/ghc29076_0/ghc29076_1.o' '-DTABLES_NEXT_TO_CODE' '-I/usr/lib/ghc/include' 
*** Linker: 
'/usr/bin/gcc' '-fno-stack-protector' '-Wl,--hash-size=31' '-Wl,--reduce-memory-overheads' '-o' 'hello' 'hello.o' '-L/usr/lib/ghc/base-4.6.0.1' '-L/usr/lib/ghc/integer-gmp-0.5.0.0' '-L/usr/lib/ghc/ghc-prim-0.3.0.0' '-L/usr/lib/ghc' '/tmp/ghc29076_0/ghc29076_0.o' '/tmp/ghc29076_0/ghc29076_1.o' '-lHSbase-4.6.0.1' '-lHSinteger-gmp-0.5.0.0' '-lgmp' '-lHSghc-prim-0.3.0.0' '-lHSrts' '-lffi' '-lm' '-lrt' '-ldl' '-u' 'ghczmprim_GHCziTypes_Izh_static_info' '-u' 'ghczmprim_GHCziTypes_Czh_static_info' '-u' 'ghczmprim_GHCziTypes_Fzh_static_info' '-u' 'ghczmprim_GHCziTypes_Dzh_static_info' '-u' 'base_GHCziPtr_Ptr_static_info' '-u' 'ghczmprim_GHCziTypes_Wzh_static_info' '-u' 'base_GHCziInt_I8zh_static_info' '-u' 'base_GHCziInt_I16zh_static_info' '-u' 'base_GHCziInt_I32zh_static_info' '-u' 'base_GHCziInt_I64zh_static_info' '-u' 'base_GHCziWord_W8zh_static_info' '-u' 'base_GHCziWord_W16zh_static_info' '-u' 'base_GHCziWord_W32zh_static_info' '-u' 'base_GHCziWord_W64zh_static_info' '-u' 'base_GHCziStable_StablePtr_static_info' '-u' 'ghczmprim_GHCziTypes_Izh_con_info' '-u' 'ghczmprim_GHCziTypes_Czh_con_info' '-u' 'ghczmprim_GHCziTypes_Fzh_con_info' '-u' 'ghczmprim_GHCziTypes_Dzh_con_info' '-u' 'base_GHCziPtr_Ptr_con_info' '-u' 'base_GHCziPtr_FunPtr_con_info' '-u' 'base_GHCziStable_StablePtr_con_info' '-u' 'ghczmprim_GHCziTypes_False_closure' '-u' 'ghczmprim_GHCziTypes_True_closure' '-u' 'base_GHCziPack_unpackCString_closure' '-u' 'base_GHCziIOziException_stackOverflow_closure' '-u' 'base_GHCziIOziException_heapOverflow_closure' '-u' 'base_ControlziExceptionziBase_nonTermination_closure' '-u' 'base_GHCziIOziException_blockedIndefinitelyOnMVar_closure' '-u' 'base_GHCziIOziException_blockedIndefinitelyOnSTM_closure' '-u' 'base_ControlziExceptionziBase_nestedAtomically_closure' '-u' 'base_GHCziWeak_runFinalizzerBatch_closure' '-u' 'base_GHCziTopHandler_flushStdHandles_closure' '-u' 'base_GHCziTopHandler_runIO_closure' '-u' 'base_GHCziTopHandler_runNonIO_closure' '-u' 'base_GHCziConcziIO_ensureIOManagerIsRunning_closure' '-u' 'base_GHCziConcziSync_runSparks_closure' '-u' 'base_GHCziConcziSignal_runHandlers_closure' 

bei den ersten beiden Dateien der Suche zeigt, dass Die c-Datei ist nur:

#include "Rts.h" 
extern StgClosure ZCMain_main_closure; 
int main(int argc, char *argv[]) 
{ 
    RtsConfig __conf = defaultRtsConfig; 
    __conf.rts_opts_enabled = RtsOptsSafeOnly; 
    return hs_main(argc, argv, &ZCMain_main_closure,__conf); 
} 

Scheint nicht so, dass sich viel von Projekt zu Projekt ändern sollte.

Die Baugruppendatei ist:

.section .debug-ghc-link-info,"",@note 
.ascii "([\"-lHSbase-4.6.0.1\",\"-lHSinteger-gmp-0.5.0.0\",\"-lgmp\",\"-lHSghc-prim-0.3.0.0\",\"-lHSrts\",\"-lffi\ ",\"-lm\",\"-lrt\",\"-ldl\",\"-u\",\"ghczmprim_GHCziTypes_Izh_static_info\",\"-u\",\"ghczmprim_GHCziTypes_Czh_static _info\",\"-u\",\"ghczmprim_GHCziTypes_Fzh_static_info\",\"-u\",\"ghczmprim_GHCziTypes_Dzh_static_info\",\"-u\",\"bas e_GHCziPtr_Ptr_static_info\",\"-u\",\"ghczmprim_GHCziTypes_Wzh_static_info\",\"-u\",\"base_GHCziInt_I8zh_static_info \",\"-u\",\"base_GHCziInt_I16zh_static_info\",\"-u\",\"base_GHCziInt_I32zh_static_info\",\"-u\",\"base_GHCziInt_I64z h_static_info\",\"-u\",\"base_GHCziWord_W8zh_static_info\",\"-u\",\"base_GHCziWord_W16zh_static_info\",\"-u\",\"base _GHCziWord_W32zh_static_info\",\"-u\",\"base_GHCziWord_W64zh_static_info\",\"-u\",\"base_GHCziStable_StablePtr_stati c_info\",\"-u\",\"ghczmprim_GHCziTypes_Izh_con_info\",\"-u\",\"ghczmprim_GHCziTypes_Czh_con_info\",\"-u\",\"ghczmpri m_GHCziTypes_Fzh_con_info\",\"-u\",\"ghczmprim_GHCziTypes_Dzh_con_info\",\"-u\",\"base_GHCziPtr_Ptr_con_info\",\"-u\ ",\"base_GHCziPtr_FunPtr_con_info\",\"-u\",\"base_GHCziStable_StablePtr_con_info\",\"-u\",\"ghczmprim_GHCziTypes_Fal se_closure\",\"-u\",\"ghczmprim_GHCziTypes_True_closure\",\"-u\",\"base_GHCziPack_unpackCString_closure\",\"-u\",\"b ase_GHCziIOziException_stackOverflow_closure\",\"-u\",\"base_GHCziIOziException_heapOverflow_closure\",\"-u\",\"base _ControlziExceptionziBase_nonTermination_closure\",\"-u\",\"base_GHCziIOziException_blockedIndefinitelyOnMVar_closur e\",\"-u\",\"base_GHCziIOziException_blockedIndefinitelyOnSTM_closure\",\"-u\",\"base_ControlziExceptionziBase_neste dAtomically_closure\",\"-u\",\"base_GHCziWeak_runFinalizzerBatch_closure\",\"-u\",\"base_GHCziTopHandler_flushStdHan dles_closure\",\"-u\",\"base_GHCziTopHandler_runIO_closure\",\"-u\",\"base_GHCziTopHandler_runNonIO_closure\",\"-u\" ,\"base_GHCziConcziIO_ensureIOManagerIsRunning_closure\",\"-u\",\"base_GHCziConcziSync_runSparks_closure\",\"-u\",\" base_GHCziConcziSignal_runHandlers_closure\"],[],Nothing,RtsOptsSafeOnly,False,[],[])" 

Nun, das ist ein wenig schlechter, aber es sieht aus wie diejenigen, die eine Liste von Linker-Flags mit einigen Kauderwelsch sind, die in GHC am Ende übergeben wurden. Ich bin mir nicht sicher was alle Dinge, die der Linker undefiniert ist, und Linker Flags betrachten wird Ihre größte Hausaufgabe sein. Müssen Sie diese Flaggen ändern? Vielleicht und vielleicht nur, wenn sich Abhängigkeiten ändern.

+0

Was den anderen Teil deiner Frage angeht, hast du wahrscheinlich den CORE durch einen anderen ersetzt, und du bist wahrscheinlich nicht ganz sicher, was dein Ziel ist. – Llamadonica

+0

hmm, ok, vielleicht ist das der Weg, um die Objektdatei manuell zu verknüpfen, aber ich hoffe, dass GHC einige Routinen hat, die das für uns erledigen. Ich meine - manchmal könnte sich das ändern und die Unterstützung wäre viel einfacher, wenn es von ghc gehandhabt würde. @Llamadonica Ich möchte meine eigene Sprache zu CORE kompilieren und dann mit normaler GHC-Pipeline fortfahren. –

5

Generieren textuelle Darstellung des Kerns ist hier kein Problem, da es auf mehrere Arten hergestellt werden kann. Sie können -fext-core Flag verwenden, um .hcr Dateien zu generieren und mit ihnen arbeiten, z. extcore. Es gibt auch andere Pakete, die einen Core ausgeben können, wie ghc-core oder ghc-core-html.

Das Hauptproblem hier ist Laden von Ghc-Core in ghc. Soweit ich weiß, wurde es unterstützt, aber jetzt ist es nicht, weil es ein geringes Interesse an der Verwendung gab und es mit der Zeit obsolet wurde.

Das Beste, was wir hier versuchen können, ist mehr in ghc Interna graben, Orte finden, wo Ghc-Core verwendet wird und versuchen, es dort zu ändern. Vielleicht können wir auch versuchen, einen ghc plugin zu erstellen und Kern damit zu ändern.

+0

Ich bin nicht daran interessiert, den Textkern zu erstellen, weil ich seinen AST generieren möchte. Das Laden des externen Kerns zu GHC wird eine Lösung sein, aber wie du es geschrieben hast, wird es nicht mehr gepflegt - die gleiche Antwort, die ich auf der Mailingliste bekommen habe.Ich bin immer noch sehr daran interessiert, die "echte" Lösung zu bekommen, aber für jetzt werde ich nur das Kopfgeld hier fallen lassen, weil die Zeit vorbei ist :( –