1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-15 01:52:11 +03:00
juvix/test/BackendC/Base.hs
Paul Cadman 433e882189
Export all functions with alpha numeric names from entrypoint module (#1425)
* Export all functions with alphanum names in entrypoint

Set the export_name attribute on every function signature that has a
fully alpha numeric name.

* Adds a non-WASI target to compile command

WASM libraries we want to run in the browser and in Anoma VM do not have
access to the WASI runtime. For this usecase we need a target runtime
that does not use the WASI runtime.

A `wasi-` prefix is added to existing compile targets and introduce a new
standalone target. This target does not have IO functions like
`putStrLn` and `exit` calls `__builtin_trap` which corresponds to the
`unreachable` WASM instruction.

In the non-exhaustive case error a debug message is emitted to tell the
user which function had the error. This is now abstracted to a `debug`
function in the runtime which calls `putStrLn` in the case of WASI and
is no-op in the case of non-WASI.

Tests are added which check that exported names can be called with the
correct name and result.

* Moves walloc to a common directory
2022-08-01 12:53:19 +02:00

159 lines
4.8 KiB
Haskell

module BackendC.Base where
import Base
import Data.FileEmbed
import Data.Text.IO qualified as TIO
import Juvix.Pipeline
import Juvix.Translation.MicroJuvixToMiniC as MiniC
import System.IO.Extra (withTempDir)
import System.Process qualified as P
clangCompile ::
(FilePath -> FilePath -> [String]) ->
MiniC.MiniCResult ->
(FilePath -> IO Text) ->
(String -> IO ()) ->
IO Text
clangCompile mkClangArgs cResult execute step =
withTempDir
( \dirPath -> do
let cOutputFile = dirPath </> "out.c"
wasmOutputFile = dirPath </> "out.wasm"
TIO.writeFile cOutputFile (cResult ^. MiniC.resultCCode)
step "WASM generation"
P.callProcess
"clang"
(mkClangArgs wasmOutputFile cOutputFile)
step "WASM execution"
execute wasmOutputFile
)
wasmClangAssertion :: WASMInfo -> FilePath -> FilePath -> ((String -> IO ()) -> Assertion)
wasmClangAssertion WASMInfo {..} mainFile expectedFile step = do
step "Check clang and wasmer are on path"
assertCmdExists "clang"
assertCmdExists "wasmer"
step "C Generation"
let entryPoint = defaultEntryPoint mainFile
p :: MiniC.MiniCResult <- runIO (upToMiniC entryPoint)
expected <- TIO.readFile expectedFile
let execute :: FilePath -> IO Text
execute outputFile =
pack
<$> P.readProcess
"wasmer"
(["run", outputFile, "--invoke", unpack _wasmInfoFunctionName] <> (unpack <$> _wasmInfoFunctionArgs))
""
step "Compile C with wasm standalone runtime"
actualStandalone <- clangCompile standaloneArgs p execute step
step "Compare expected and actual program output"
assertEqDiff ("Check: WASM output = " <> expectedFile) actualStandalone expected
wasiClangAssertion :: StdlibMode -> FilePath -> FilePath -> Text -> ((String -> IO ()) -> Assertion)
wasiClangAssertion stdlibMode mainFile expectedFile stdinText step = do
step "Check clang and wasmer are on path"
assertCmdExists "clang"
assertCmdExists "wasmer"
step "Lookup WASI_SYSROOT_PATH"
sysrootPath <-
assertEnvVar
"Env var WASI_SYSROOT_PATH missing. Set to the location of the wasi-clib sysroot"
"WASI_SYSROOT_PATH"
step "C Generation"
let entryPoint = (defaultEntryPoint mainFile) {_entryPointNoStdlib = stdlibMode == StdlibExclude}
p :: MiniC.MiniCResult <- runIO (upToMiniC entryPoint)
expected <- TIO.readFile expectedFile
let execute :: FilePath -> IO Text
execute outputFile = pack <$> P.readProcess "wasmer" [outputFile] (unpack stdinText)
step "Compile C with standalone runtime"
actualStandalone <- clangCompile (wasiStandaloneArgs sysrootPath) p execute step
step "Compare expected and actual program output"
assertEqDiff ("check: WASM output = " <> expectedFile) actualStandalone expected
step "Compile C with libc runtime"
actualLibc <- clangCompile (libcArgs sysrootPath) p execute step
step "Compare expected and actual program output"
assertEqDiff ("check: WASM output = " <> expectedFile) actualLibc expected
builtinRuntime :: FilePath
builtinRuntime = $(makeRelativeToProject "minic-runtime/builtins" >>= strToExp)
standaloneArgs :: FilePath -> FilePath -> [String]
standaloneArgs wasmOutputFile cOutputFile =
[ "-nodefaultlibs",
"-std=c99",
"-Oz",
"-I",
takeDirectory minicRuntime,
"-I",
builtinRuntime,
"-Werror",
"--target=wasm32",
"-nostartfiles",
"-Wl,--no-entry",
"-o",
wasmOutputFile,
wallocPath,
cOutputFile
]
where
minicRuntime :: FilePath
minicRuntime = $(makeRelativeToProject "minic-runtime/standalone/minic-runtime.h" >>= strToExp)
wallocPath :: FilePath
wallocPath = $(makeRelativeToProject "minic-runtime/walloc/walloc.c" >>= strToExp)
wasiStandaloneArgs :: FilePath -> FilePath -> FilePath -> [String]
wasiStandaloneArgs sysrootPath wasmOutputFile cOutputFile =
[ "-nodefaultlibs",
"-std=c99",
"-Oz",
"-I",
takeDirectory minicRuntime,
"-I",
builtinRuntime,
"-Werror",
"--target=wasm32-wasi",
"--sysroot",
sysrootPath,
"-o",
wasmOutputFile,
wallocPath,
cOutputFile
]
where
minicRuntime :: FilePath
minicRuntime = $(makeRelativeToProject "minic-runtime/wasi-standalone/minic-runtime.h" >>= strToExp)
wallocPath :: FilePath
wallocPath = $(makeRelativeToProject "minic-runtime/walloc/walloc.c" >>= strToExp)
libcArgs :: FilePath -> FilePath -> FilePath -> [String]
libcArgs sysrootPath wasmOutputFile cOutputFile =
[ "-nodefaultlibs",
"-std=c99",
"-Oz",
"-I",
takeDirectory minicRuntime,
"-I",
builtinRuntime,
"-Werror",
"-lc",
"--target=wasm32-wasi",
"--sysroot",
sysrootPath,
"-o",
wasmOutputFile,
cOutputFile
]
where
minicRuntime :: FilePath
minicRuntime = $(makeRelativeToProject "minic-runtime/wasi-libc/minic-runtime.h" >>= strToExp)