-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implements code generation through Rust. * CLI: adds two `dev` compilation targets: 1. `rust` for generating Rust code 2. `native-rust` for generating a native executable via Rust * Adds end-to-end tests for compilation from Juvix to native executable via Rust. * A target for RISC0 needs to be added in a separate PR building on this one.
- Loading branch information
Showing
174 changed files
with
3,585 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
module Commands.Dev.DevCompile.NativeRust where | ||
|
||
import Commands.Base | ||
import Commands.Dev.DevCompile.NativeRust.Options | ||
import Commands.Extra.Rust | ||
import Data.ByteString qualified as BS | ||
import Data.FileEmbed qualified as FE | ||
import Juvix.Compiler.Backend.Rust.Data.Result | ||
|
||
runCommand :: | ||
(Members '[App, EmbedIO, TaggedLock] r) => | ||
NativeRustOptions 'InputMain -> | ||
Sem r () | ||
runCommand opts = do | ||
let opts' = opts ^. nativeRustCompileCommonOptions | ||
inputFile = opts' ^. compileInputFile | ||
moutputFile = opts' ^. compileOutputFile | ||
mainFile <- getMainFile inputFile | ||
Result {..} <- runPipeline opts inputFile upToRust | ||
rustFile <- inputRustFile mainFile | ||
writeFileEnsureLn rustFile _resultRustCode | ||
buildDir <- askBuildDir | ||
ensureDir buildDir | ||
prepareRuntime | ||
outputFile <- nativeOutputFile mainFile moutputFile | ||
let args = | ||
RustArgs | ||
{ _rustDebug = opts' ^. compileDebug, | ||
_rustInputFile = rustFile, | ||
_rustOutputFile = outputFile, | ||
_rustOptimizationLevel = fmap (min 3 . (+ 1)) (opts' ^. compileOptimizationLevel) | ||
} | ||
rustCompile args | ||
where | ||
prepareRuntime :: | ||
forall s. | ||
(Members '[App, EmbedIO] s) => | ||
Sem s () | ||
prepareRuntime = writeRuntime runtime | ||
where | ||
runtime :: BS.ByteString | ||
runtime | ||
| opts ^. nativeRustCompileCommonOptions . compileDebug = rustDebugRuntime | ||
| otherwise = rustReleaseRuntime | ||
where | ||
rustReleaseRuntime :: BS.ByteString | ||
rustReleaseRuntime = $(FE.makeRelativeToProject "runtime/rust/target/release/libjuvix.rlib" >>= FE.embedFile) | ||
|
||
rustDebugRuntime :: BS.ByteString | ||
rustDebugRuntime = $(FE.makeRelativeToProject "runtime/rust/target/debug/libjuvix.rlib" >>= FE.embedFile) | ||
|
||
inputRustFile :: (Members '[App, EmbedIO] r) => Path Abs File -> Sem r (Path Abs File) | ||
inputRustFile inputFileCompile = do | ||
buildDir <- askBuildDir | ||
ensureDir buildDir | ||
return (buildDir <//> replaceExtension' ".rs" (filename inputFileCompile)) | ||
|
||
nativeOutputFile :: forall r. (Member App r) => Path Abs File -> Maybe (AppPath File) -> Sem r (Path Abs File) | ||
nativeOutputFile inputFile moutputFile = | ||
case moutputFile of | ||
Just f -> fromAppFile f | ||
Nothing -> do | ||
invokeDir <- askInvokeDir | ||
let baseOutputFile = invokeDir <//> filename inputFile | ||
return $ removeExtension' baseOutputFile | ||
|
||
writeRuntime :: | ||
forall r. | ||
(Members '[App, EmbedIO] r) => | ||
BS.ByteString -> | ||
Sem r () | ||
writeRuntime runtime = do | ||
buildDir <- askBuildDir | ||
liftIO $ | ||
BS.writeFile (toFilePath (buildDir <//> $(mkRelFile "libjuvix.rlib"))) runtime |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{-# LANGUAGE UndecidableInstances #-} | ||
|
||
module Commands.Dev.DevCompile.NativeRust.Options | ||
( module Commands.Dev.DevCompile.NativeRust.Options, | ||
module Commands.Compile.CommonOptions, | ||
) | ||
where | ||
|
||
import Commands.Compile.CommonOptions | ||
import CommonOptions | ||
|
||
data NativeRustOptions (k :: InputKind) = NativeRustOptions | ||
{ _nativeRustCompileCommonOptions :: CompileCommonOptions k | ||
} | ||
|
||
deriving stock instance (Typeable k, Data (InputFileType k)) => Data (NativeRustOptions k) | ||
|
||
makeLenses ''NativeRustOptions | ||
|
||
parseNativeRust :: (SingI k) => Parser (NativeRustOptions k) | ||
parseNativeRust = do | ||
_nativeRustCompileCommonOptions <- parseCompileCommonOptions | ||
pure NativeRustOptions {..} | ||
|
||
instance EntryPointOptions (NativeRustOptions k) where | ||
applyOptions opts = | ||
set entryPointTarget (Just TargetRust) | ||
. applyOptions (opts ^. nativeRustCompileCommonOptions) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Commands.Dev.DevCompile.Rust where | ||
|
||
import Commands.Base | ||
import Commands.Dev.DevCompile.Rust.Options | ||
import Commands.Extra.NewCompile | ||
import Juvix.Compiler.Backend.Rust.Data.Result | ||
|
||
runCommand :: | ||
(Members '[App, EmbedIO, TaggedLock] r) => | ||
RustOptions 'InputMain -> | ||
Sem r () | ||
runCommand opts = do | ||
let inputFile = opts ^. rustCompileCommonOptions . compileInputFile | ||
moutputFile = opts ^. rustCompileCommonOptions . compileOutputFile | ||
outFile :: Path Abs File <- getOutputFile FileExtRust inputFile moutputFile | ||
Result {..} <- runPipeline opts inputFile upToRust | ||
writeFileEnsureLn outFile _resultRustCode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{-# LANGUAGE UndecidableInstances #-} | ||
|
||
module Commands.Dev.DevCompile.Rust.Options | ||
( module Commands.Dev.DevCompile.Rust.Options, | ||
module Commands.Compile.CommonOptions, | ||
) | ||
where | ||
|
||
import Commands.Compile.CommonOptions | ||
import CommonOptions | ||
|
||
data RustOptions (k :: InputKind) = RustOptions | ||
{ _rustCompileCommonOptions :: CompileCommonOptions k | ||
} | ||
|
||
deriving stock instance (Typeable k, Data (InputFileType k)) => Data (RustOptions k) | ||
|
||
makeLenses ''RustOptions | ||
|
||
parseRust :: (SingI k) => Parser (RustOptions k) | ||
parseRust = do | ||
_rustCompileCommonOptions <- parseCompileCommonOptions | ||
pure RustOptions {..} | ||
|
||
instance EntryPointOptions (RustOptions k) where | ||
applyOptions opts = | ||
set entryPointTarget (Just TargetRust) | ||
. applyOptions (opts ^. rustCompileCommonOptions) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
module Commands.Extra.Rust where | ||
|
||
import Commands.Base | ||
import System.Process qualified as P | ||
|
||
data RustArgs = RustArgs | ||
{ _rustDebug :: Bool, | ||
_rustInputFile :: Path Abs File, | ||
_rustOutputFile :: Path Abs File, | ||
_rustOptimizationLevel :: Maybe Int | ||
} | ||
|
||
makeLenses ''RustArgs | ||
|
||
rustCompile :: | ||
forall r. | ||
(Members '[App, EmbedIO] r) => | ||
RustArgs -> | ||
Sem r () | ||
rustCompile args = do | ||
getRustcCliArgs args >>= runRustc | ||
|
||
getRustcCliArgs :: (Members '[App, EmbedIO] r) => RustArgs -> Sem r [String] | ||
getRustcCliArgs args = do | ||
buildDir <- askBuildDir | ||
return (nativeArgs buildDir args) | ||
|
||
nativeArgs :: Path Abs Dir -> RustArgs -> [String] | ||
nativeArgs buildDir args@RustArgs {..} = | ||
commonArgs buildDir args ++ extraArgs | ||
where | ||
extraArgs :: [String] | ||
extraArgs = run . execAccumList $ do | ||
addOptimizationOption args | ||
addArg (toFilePath _rustInputFile) | ||
|
||
addOptimizationOption :: (Member (Accum String) r) => RustArgs -> Sem r () | ||
addOptimizationOption args = do | ||
addArg "-C" | ||
addArg $ "opt-level=" <> show (maybe defaultOptLevel (max 1) (args ^. rustOptimizationLevel)) | ||
where | ||
defaultOptLevel :: Int | ||
defaultOptLevel | ||
| args ^. rustDebug = debugRustOptimizationLevel | ||
| otherwise = defaultRustOptimizationLevel | ||
|
||
debugRustOptimizationLevel :: Int | ||
debugRustOptimizationLevel = 1 | ||
|
||
defaultRustOptimizationLevel :: Int | ||
defaultRustOptimizationLevel = 3 | ||
|
||
addArg :: (Member (Accum String) r) => String -> Sem r () | ||
addArg = accum | ||
|
||
commonArgs :: Path Abs Dir -> RustArgs -> [String] | ||
commonArgs buildDir RustArgs {..} = run . execAccumList $ do | ||
when _rustDebug $ do | ||
addArg "-g" | ||
addArg "-C" | ||
addArg "debug-assertions=true" | ||
addArg "-C" | ||
addArg "overflow-checks=true" | ||
addArg "-o" | ||
addArg (toFilePath _rustOutputFile) | ||
addArg ("-L") | ||
addArg (toFilePath buildDir) | ||
|
||
runRustc :: | ||
forall r. | ||
(Members '[App, EmbedIO] r) => | ||
[String] -> | ||
Sem r () | ||
runRustc args = do | ||
cp <- rustcBinPath | ||
(exitCode, _, err) <- liftIO (P.readProcessWithExitCode cp args "") | ||
case exitCode of | ||
ExitSuccess -> return () | ||
_ -> exitFailMsg (pack err) | ||
where | ||
rustcBinPath :: Sem r String | ||
rustcBinPath = do | ||
p <- findExecutable $(mkRelFile "rustc") | ||
maybe (exitFailMsg rustcNotFoundErr) (return . toFilePath) p | ||
|
||
rustcNotFoundErr :: Text | ||
rustcNotFoundErr = "Error: The rustc executable was not found. Please install the Rust compiler" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.