1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-15 01:52:11 +03:00
juvix/app/Commands/Compile.hs

175 lines
5.9 KiB
Haskell
Raw Normal View History

module Commands.Compile where
2022-09-14 17:16:15 +03:00
import Commands.Base
import Commands.Compile.Options
import Data.ByteString qualified as BS
import Data.FileEmbed qualified as FE
import Data.Text.IO qualified as TIO
2022-09-14 17:16:15 +03:00
import Juvix.Compiler.Backend.C.Translation.FromInternal qualified as MiniC
import System.Environment
import System.Process qualified as P
2022-09-14 17:16:15 +03:00
runCommand :: Members '[Embed IO, App] r => CompileOptions -> Sem r ()
runCommand opts@CompileOptions {..} = do
root <- askRoot
miniC <- (^. MiniC.resultCCode) <$> runPipeline _compileInputFile upToMiniC
let inputFile = _compileInputFile ^. pathPath
result <- embed (runCompile root inputFile opts miniC)
case result of
Left err -> printFailureExit err
_ -> return ()
juvixBuildDir :: FilePath
juvixBuildDir = ".juvix-build"
inputCFile :: FilePath -> FilePath -> FilePath
2022-09-14 17:16:15 +03:00
inputCFile projRoot inputFileCompile =
projRoot </> juvixBuildDir </> outputMiniCFile
where
outputMiniCFile :: FilePath
2022-09-14 17:16:15 +03:00
outputMiniCFile = takeBaseName inputFileCompile <> ".c"
runCompile :: FilePath -> FilePath -> CompileOptions -> Text -> IO (Either Text ())
2022-09-14 17:16:15 +03:00
runCompile projRoot inputFileCompile o minic = do
createDirectoryIfMissing True (projRoot </> juvixBuildDir)
2022-09-14 17:16:15 +03:00
TIO.writeFile (inputCFile projRoot inputFileCompile) minic
prepareRuntime projRoot o
case o ^. compileTarget of
2022-09-14 17:16:15 +03:00
TargetWasm -> runM (runError (clangCompile projRoot inputFileCompile o))
TargetC -> return (Right ())
2022-09-14 17:16:15 +03:00
TargetNative -> runM (runError (clangNativeCompile projRoot inputFileCompile o))
prepareRuntime :: FilePath -> CompileOptions -> IO ()
prepareRuntime projRoot o = do
mapM_ writeRuntime runtimeProjectDir
where
wasiStandaloneRuntimeDir :: [(FilePath, BS.ByteString)]
wasiStandaloneRuntimeDir = $(FE.makeRelativeToProject "c-runtime/wasi-standalone" >>= FE.embedDir)
standaloneRuntimeDir :: [(FilePath, BS.ByteString)]
standaloneRuntimeDir = $(FE.makeRelativeToProject "c-runtime/standalone" >>= FE.embedDir)
wasiLibCRuntimeDir :: [(FilePath, BS.ByteString)]
wasiLibCRuntimeDir = $(FE.makeRelativeToProject "c-runtime/wasi-libc" >>= FE.embedDir)
Add support for built in types (#192) * match inductive definitions * progress towards builtins * more progress towards builtin types * add more builtins * add some errors * add reverse table to builtins * Squashed commit of the following: commit 93333de502d8dd546eb8edf697ca7eef972ea105 Author: Paul Cadman <git@paulcadman.dev> Date: Mon Jun 27 18:21:30 2022 +0100 Use builtin names for match and project functions Add an implementation of nat for the standalone backend commit 868d2098ee57b7acbca84512b6e096650eeeb22d Author: Jan Mas Rovira <janmasrovira@gmail.com> Date: Mon Jun 27 18:15:29 2022 +0200 add builtin information to ClosureInfo commit 32c78aceb19ee4010d66090a3c4e6025621b5c1f Author: Paul Cadman <git@paulcadman.dev> Date: Mon Jun 27 12:52:10 2022 +0100 Refactor BuiltinEnum to sum type of each Builtin commit 55bb72ab12a8fb7d10070c2dee5875482453b7c6 Author: Paul Cadman <git@paulcadman.dev> Date: Fri Jun 24 14:44:28 2022 +0100 Add Builtin information to Mono InfoTable commit a72368f2e3af20baaf44c5e21fa7e6a469cf1ac5 Author: Paul Cadman <git@paulcadman.dev> Date: Fri Jun 24 14:41:51 2022 +0100 Add Bitraversable to Prelude commit afa3153d82a9509b0882e7ca99830040fad9ef65 Author: Paul Cadman <git@paulcadman.dev> Date: Fri Jun 24 14:41:39 2022 +0100 Remove unused import commit ea0b7848fb80970e03a0561be3fb4448486a89a9 Author: Paul Cadman <git@paulcadman.dev> Date: Thu Jun 23 13:54:58 2022 +0100 Use projection functions instead of direct member access * Avoid shadowing C runtime names in foreign block * Fix formatting * Update C names for builtin functions * Add prim_ prefix to builtin C names Implement builtins for standalone and libc backends * Update ormolu action * ci: run all tests for draft PRs Co-authored-by: Paul Cadman <git@paulcadman.dev>
2022-06-28 14:31:31 +03:00
builtinCRuntimeDir :: [(FilePath, BS.ByteString)]
builtinCRuntimeDir = $(FE.makeRelativeToProject "c-runtime/builtins" >>= FE.embedDir)
Add support for built in types (#192) * match inductive definitions * progress towards builtins * more progress towards builtin types * add more builtins * add some errors * add reverse table to builtins * Squashed commit of the following: commit 93333de502d8dd546eb8edf697ca7eef972ea105 Author: Paul Cadman <git@paulcadman.dev> Date: Mon Jun 27 18:21:30 2022 +0100 Use builtin names for match and project functions Add an implementation of nat for the standalone backend commit 868d2098ee57b7acbca84512b6e096650eeeb22d Author: Jan Mas Rovira <janmasrovira@gmail.com> Date: Mon Jun 27 18:15:29 2022 +0200 add builtin information to ClosureInfo commit 32c78aceb19ee4010d66090a3c4e6025621b5c1f Author: Paul Cadman <git@paulcadman.dev> Date: Mon Jun 27 12:52:10 2022 +0100 Refactor BuiltinEnum to sum type of each Builtin commit 55bb72ab12a8fb7d10070c2dee5875482453b7c6 Author: Paul Cadman <git@paulcadman.dev> Date: Fri Jun 24 14:44:28 2022 +0100 Add Builtin information to Mono InfoTable commit a72368f2e3af20baaf44c5e21fa7e6a469cf1ac5 Author: Paul Cadman <git@paulcadman.dev> Date: Fri Jun 24 14:41:51 2022 +0100 Add Bitraversable to Prelude commit afa3153d82a9509b0882e7ca99830040fad9ef65 Author: Paul Cadman <git@paulcadman.dev> Date: Fri Jun 24 14:41:39 2022 +0100 Remove unused import commit ea0b7848fb80970e03a0561be3fb4448486a89a9 Author: Paul Cadman <git@paulcadman.dev> Date: Thu Jun 23 13:54:58 2022 +0100 Use projection functions instead of direct member access * Avoid shadowing C runtime names in foreign block * Fix formatting * Update C names for builtin functions * Add prim_ prefix to builtin C names Implement builtins for standalone and libc backends * Update ormolu action * ci: run all tests for draft PRs Co-authored-by: Paul Cadman <git@paulcadman.dev>
2022-06-28 14:31:31 +03:00
wallocDir :: [(FilePath, BS.ByteString)]
wallocDir = $(FE.makeRelativeToProject "c-runtime/walloc" >>= FE.embedDir)
libcRuntime :: [(FilePath, BS.ByteString)]
libcRuntime = wasiLibCRuntimeDir <> builtinCRuntimeDir
runtimeProjectDir :: [(FilePath, BS.ByteString)]
runtimeProjectDir = case o ^. compileTarget of
TargetNative -> libcRuntime
_ -> case o ^. compileRuntime of
RuntimeWasiStandalone -> wasiStandaloneRuntimeDir <> builtinCRuntimeDir <> wallocDir
RuntimeWasiLibC -> libcRuntime
RuntimeStandalone -> standaloneRuntimeDir <> builtinCRuntimeDir <> wallocDir
writeRuntime :: (FilePath, BS.ByteString) -> IO ()
writeRuntime (filePath, contents) =
BS.writeFile (projRoot </> juvixBuildDir </> takeFileName filePath) contents
clangNativeCompile ::
forall r.
Members '[Embed IO, Error Text] r =>
FilePath ->
FilePath ->
CompileOptions ->
Sem r ()
2022-09-14 17:16:15 +03:00
clangNativeCompile projRoot inputFileCompile o = runClang (nativeArgs outputFile inputFile)
where
outputFile :: FilePath
2022-09-14 17:16:15 +03:00
outputFile = maybe (takeBaseName inputFileCompile) (^. pathPath) (o ^. compileOutputFile)
inputFile :: FilePath
2022-09-14 17:16:15 +03:00
inputFile = inputCFile projRoot inputFileCompile
clangCompile ::
forall r.
Members '[Embed IO, Error Text] r =>
FilePath ->
FilePath ->
CompileOptions ->
Sem r ()
2022-09-14 17:16:15 +03:00
clangCompile projRoot inputFileCompile o = clangArgs >>= runClang
where
clangArgs :: Sem r [String]
clangArgs = case o ^. compileRuntime of
RuntimeStandalone ->
return (standaloneLibArgs projRoot outputFile inputFile)
RuntimeWasiStandalone -> wasiStandaloneArgs projRoot outputFile inputFile <$> sysrootEnvVar
RuntimeWasiLibC -> wasiLibcArgs outputFile inputFile <$> sysrootEnvVar
outputFile :: FilePath
2022-09-14 17:16:15 +03:00
outputFile = maybe (takeBaseName inputFileCompile <> ".wasm") (^. pathPath) (o ^. compileOutputFile)
inputFile :: FilePath
2022-09-14 17:16:15 +03:00
inputFile = inputCFile projRoot inputFileCompile
sysrootEnvVar :: Sem r String
sysrootEnvVar =
fromMaybeM (throw msg) (embed (lookupEnv "WASI_SYSROOT_PATH"))
where
msg :: Text
msg = "Missing environment variable WASI_SYSROOT_PATH"
commonArgs :: FilePath -> [String]
commonArgs wasmOutputFile =
[ "-std=c99",
"-Oz",
"-I",
juvixBuildDir,
"-o",
wasmOutputFile
]
standaloneLibArgs :: FilePath -> FilePath -> FilePath -> [String]
standaloneLibArgs projRoot wasmOutputFile inputFile =
commonArgs wasmOutputFile
<> [ "--target=wasm32",
"-nodefaultlibs",
"-nostartfiles",
"-Wl,--no-entry",
projRoot </> juvixBuildDir </> "walloc.c",
inputFile
]
wasiStandaloneArgs :: FilePath -> FilePath -> FilePath -> FilePath -> [String]
wasiStandaloneArgs projRoot wasmOutputFile inputFile sysrootPath =
wasiCommonArgs sysrootPath wasmOutputFile
<> [ projRoot </> juvixBuildDir </> "walloc.c",
inputFile
]
wasiLibcArgs :: FilePath -> FilePath -> FilePath -> [String]
wasiLibcArgs wasmOutputFile inputFile sysrootPath =
wasiCommonArgs sysrootPath wasmOutputFile
<> ["-lc", inputFile]
nativeArgs :: FilePath -> FilePath -> [String]
nativeArgs outputFile inputFile =
commonArgs outputFile <> [inputFile]
wasiCommonArgs :: FilePath -> FilePath -> [String]
wasiCommonArgs sysrootPath wasmOutputFile =
commonArgs wasmOutputFile
<> [ "-nodefaultlibs",
"--target=wasm32-wasi",
"--sysroot",
sysrootPath
]
runClang ::
Members '[Embed IO, Error Text] r =>
[String] ->
Sem r ()
runClang args = do
(exitCode, _, err) <- embed (P.readProcessWithExitCode "clang" args "")
case exitCode of
ExitSuccess -> return ()
_ -> throw (pack err)