#include "HsVersions.h"
#ifndef OMIT_NATIVE_CODEGEN
-import UniqSupply ( mkSplitUniqSupply )
import AsmCodeGen ( nativeCodeGen )
#endif
+import LlvmCodeGen ( llvmCodeGen )
+
+import UniqSupply ( mkSplitUniqSupply )
#ifdef JAVA
import JavaGen ( javaGen )
import PprC ( writeCs )
import CmmLint ( cmmLint )
import Packages
-import PackageConfig ( rtsPackageId )
import Util
-import FastString ( unpackFS )
import Cmm ( RawCmm )
import HscTypes
import DynFlags
+import Config
import ErrUtils ( dumpIfSet_dyn, showPass, ghcExit )
import Outputable
-import Pretty ( Mode(..), printDoc )
-import Module ( Module, ModLocation(..), moduleName )
-import List ( nub )
+import Module
import Maybes ( firstJust )
-import Distribution.Package ( showPackageId )
-import Directory ( doesFileExist )
-import Monad ( when )
-import IO
+import Control.Exception
+import Control.Monad
+import System.Directory
+import System.FilePath
+import System.IO
\end{code}
%************************************************************************
; stubs_exist <- outputForeignStubs dflags this_mod location foreign_stubs
; case hscTarget dflags of {
HscInterpreted -> return ();
- HscAsm -> outputAsm dflags filenm this_mod location flat_abstractC;
- HscC -> outputC dflags filenm this_mod location
- flat_abstractC stubs_exist pkg_deps
- foreign_stubs;
+ HscAsm -> outputAsm dflags filenm flat_abstractC;
+ HscC -> outputC dflags filenm flat_abstractC pkg_deps;
+ HscLlvm -> outputLlvm dflags filenm flat_abstractC;
HscJava ->
#ifdef JAVA
outputJava dflags filenm mod_name tycons core_binds;
#else
panic "Java support not compiled into this ghc";
#endif
+ HscNothing -> panic "codeOutput: HscNothing"
}
; return stubs_exist
}
%************************************************************************
\begin{code}
-outputC dflags filenm mod location flat_absC
- (stub_h_exists, _) packages foreign_stubs
+outputC :: DynFlags
+ -> FilePath
+ -> [RawCmm]
+ -> [PackageId]
+ -> IO ()
+
+outputC dflags filenm flat_absC packages
= do
-- figure out which header files to #include in the generated .hc file:
--
-- * -#include options from the cmdline and OPTIONS pragmas
-- * the _stub.h file, if there is one.
--
- pkg_configs <- getPreloadPackagesAnd dflags packages
- let pkg_names = map (showPackageId.package) pkg_configs
-
- c_includes <- getPackageCIncludes pkg_configs
- let cmdline_includes = cmdlineHcIncludes dflags -- -#include options
-
- ffi_decl_headers
- = case foreign_stubs of
- NoStubs -> []
- ForeignStubs _ _ fdhs _ -> map unpackFS (nub fdhs)
- -- Remove duplicates, because distinct foreign import decls
- -- may cite the same #include. Order doesn't matter.
-
- all_headers = c_includes
- ++ reverse cmdline_includes
- ++ ffi_decl_headers
+ let rts = getPackageDetails (pkgState dflags) rtsPackageId
- let cc_injects = unlines (map mk_include all_headers)
+ let cc_injects = unlines (map mk_include (includes rts))
mk_include h_file =
case h_file of
'"':_{-"-} -> "#include "++h_file
'<':_ -> "#include "++h_file
_ -> "#include \""++h_file++"\""
+ pkg_configs <- getPreloadPackagesAnd dflags packages
+ let pkg_names = map (display.sourcePackageId) pkg_configs
+
doOutput filenm $ \ h -> do
hPutStr h ("/* GHC_PACKAGES " ++ unwords pkg_names ++ "\n*/\n")
hPutStr h cc_injects
- when stub_h_exists $
- hPutStrLn h ("#include \"" ++ (filenameOf stub_h) ++ "\"")
writeCs dflags h flat_absC
- where
- (_, stub_h) = mkStubPaths dflags (moduleName mod) location
\end{code}
%************************************************************************
\begin{code}
-outputAsm dflags filenm this_mod location flat_absC
+outputAsm :: DynFlags -> FilePath -> [RawCmm] -> IO ()
#ifndef OMIT_NATIVE_CODEGEN
+outputAsm dflags filenm flat_absC
= do ncg_uniqs <- mkSplitUniqSupply 'n'
- ncg_output_d <- {-# SCC "NativeCodeGen" #-}
- nativeCodeGen dflags this_mod location flat_absC ncg_uniqs
- dumpIfSet_dyn dflags Opt_D_dump_asm "Asm code" (docToSDoc ncg_output_d)
+
{-# SCC "OutputAsm" #-} doOutput filenm $
- \f -> printDoc LeftMode f ncg_output_d
+ \f -> {-# SCC "NativeCodeGen" #-}
+ nativeCodeGen dflags f ncg_uniqs flat_absC
where
#else /* OMIT_NATIVE_CODEGEN */
+outputAsm _ _ _
= pprPanic "This compiler was built without a native code generator"
(text "Use -fvia-C instead")
%************************************************************************
%* *
+\subsection{LLVM}
+%* *
+%************************************************************************
+
+\begin{code}
+outputLlvm :: DynFlags -> FilePath -> [RawCmm] -> IO ()
+outputLlvm dflags filenm flat_absC
+ = do ncg_uniqs <- mkSplitUniqSupply 'n'
+ doOutput filenm $ \f -> llvmCodeGen dflags f ncg_uniqs flat_absC
+\end{code}
+
+
+%************************************************************************
+%* *
\subsection{Java}
%* *
%************************************************************************
-> IO (Bool, -- Header file created
Bool) -- C file created
outputForeignStubs dflags mod location stubs
- | NoStubs <- stubs = do
+ = case stubs of
+ NoStubs -> do
-- When compiling External Core files, may need to use stub
-- files from a previous compilation
stub_c_exists <- doesFileExist stub_c
stub_h_exists <- doesFileExist stub_h
return (stub_h_exists, stub_c_exists)
- | ForeignStubs h_code c_code _ _ <- stubs
- = do
+ ForeignStubs h_code c_code -> do
let
stub_c_output_d = pprCode CStyle c_code
stub_c_output_w = showSDoc stub_c_output_d
stub_h_output_w = showSDoc stub_h_output_d
-- in
- createDirectoryHierarchy (directoryOf stub_c)
+ createDirectoryHierarchy (takeDirectory stub_c)
dumpIfSet_dyn dflags Opt_D_dump_foreign
"Foreign export header file" stub_h_output_d
concatMap mk_include (includes rts_pkg)
mk_include i = "#include \"" ++ i ++ "\"\n"
+ -- wrapper code mentions the ffi_arg type, which comes from ffi.h
+ ffi_includes | cLibFFI = "#include \"ffi.h\"\n"
+ | otherwise = ""
+
stub_h_file_exists
<- outputForeignStubs_help stub_h stub_h_output_w
("#include \"HsFFI.h\"\n" ++ cplusplus_hdr) cplusplus_ftr
("#define IN_STG_CODE 0\n" ++
"#include \"Rts.h\"\n" ++
rts_includes ++
+ ffi_includes ++
cplusplus_hdr)
cplusplus_ftr
-- We're adding the default hc_header to the stub file, but this
return (stub_h_file_exists, stub_c_file_exists)
where
- (stub_c, stub_h) = mkStubPaths dflags (moduleName mod) location
+ (stub_c, stub_h, _) = mkStubPaths dflags (moduleName mod) location
+
+ cplusplus_hdr = "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"
+ cplusplus_ftr = "#ifdef __cplusplus\n}\n#endif\n"
-cplusplus_hdr = "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"
-cplusplus_ftr = "#ifdef __cplusplus\n}\n#endif\n"
-- Don't use doOutput for dumping the f. export stubs
-- since it is more than likely that the stubs file will
-- turn out to be empty, in which case no file should be created.
-outputForeignStubs_help fname "" header footer = return False
+outputForeignStubs_help :: FilePath -> String -> String -> String -> IO Bool
+outputForeignStubs_help _fname "" _header _footer = return False
outputForeignStubs_help fname doc_str header footer
= do writeFile fname (header ++ doc_str ++ '\n':footer ++ "\n")
return True