Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the dynamic dispatch loop in JuvixAsm #2556

Merged
merged 12 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/Commands/Dev/Asm/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ runCommand opts = do
ensureDir buildDir
cFile <- inputCFile file
embed $ TIO.writeFile (toFilePath cFile) _resultCCode
Compile.runCommand opts {_compileInputFile = Just (AppPath (preFileFromAbs cFile) False)}
outfile <- Compile.outputFile opts file
Compile.runCommand
opts
{ _compileInputFile = Just (AppPath (preFileFromAbs cFile) False),
_compileOutputFile = Just (AppPath (preFileFromAbs outfile) False)
}
where
getFile :: Sem r (Path Abs File)
getFile = getMainFile (opts ^. compileInputFile)
Expand Down
12 changes: 7 additions & 5 deletions cntlines.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ function count() {
cloc $1 | grep 'SUM:' | awk '{print $5}'
}

function count_pir () {
find $1 -name '*.pir' -print | xargs sed '/^[[:space:]]*$/d' | wc -l | tr -d ' '
function count_ext () {
find $2 -name $1 -print | xargs sed '/^[[:space:]]*$/d' | wc -l | tr -d ' '
}

RUNTIME_C=$(count runtime/src/juvix)
RUNTIME_VAMPIR=$(count_pir runtime/src/vampir)
RUNTIME_VAMPIR=$(count_ext '*.pir' runtime/src/vampir)
RUNTIME_JVA=$(count_ext '*.jva' runtime/src/asm)

RUNTIME=$((RUNTIME_C+RUNTIME_VAMPIR))
RUNTIME=$((RUNTIME_C+RUNTIME_VAMPIR+RUNTIME_JVA))

BACKENDC=$(count src/Juvix/Compiler/Backend/C/)
GEB=$(count src/Juvix/Compiler/Backend/Geb/)
Expand Down Expand Up @@ -52,6 +53,7 @@ echo " JuvixAsm: $ASM LOC"
echo " JuvixCore: $CORE LOC"
echo "Runtime: $RUNTIME LOC"
echo " C runtime: $RUNTIME_C LOC"
echo " JuvixAsm runtime: $RUNTIME_JVA LOC"
echo " VampIR runtime: $RUNTIME_VAMPIR LOC"
echo "Other: $OTHER LOC"
echo " Application: $APP LOC"
Expand All @@ -61,4 +63,4 @@ echo " Data: $DATA LOC"
echo " Prelude: $PRELUDE LOC"
echo "Tests: $TESTS LOC"
echo ""
echo "Total: $TOTAL Haskell LOC + $RUNTIME_C C LOC + $RUNTIME_VAMPIR VampIR LOC"
echo "Total: $TOTAL Haskell LOC + $RUNTIME_C C LOC + $RUNTIME_JVA JuvixAsm LOC + $RUNTIME_VAMPIR VampIR LOC"
193 changes: 193 additions & 0 deletions runtime/src/asm/apply.jva
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@

function juvix_apply_1(*, *) : * {
push arg[0];
argsnum;
push 1;
eq;
br {
true: { -- argsnum = 1
push arg[1];
push arg[0];
tcall $ 1;
}
false: { -- argsnum > 1
push arg[1];
push arg[0];
cextend 1;
ret;
}
};
}

function juvix_apply_2(*, *, *) : * {
push arg[0];
argsnum;
tsave n {
push n;
push 2;
eq;
br {
true: { -- argsnum = 2
push arg[2];
push arg[1];
push arg[0];
tcall $ 2;
}
false: {
push n;
push 1;
eq;
br {
true: { -- argsnum = 1
push arg[2];
push arg[1];
push arg[0];
call $ 1;
tcall juvix_apply_1;
}
false: { -- argsnum > 2
push arg[2];
push arg[1];
push arg[0];
cextend 2;
ret;
}
};
}
};
};
}

function juvix_apply_3(*, *, *, *) : * {
push arg[0];
argsnum;
tsave n {
push n;
push 3;
eq;
br {
true: { -- argsnum = 3
push arg[3];
push arg[2];
push arg[1];
push arg[0];
tcall $ 3;
}
false: {
push n;
push 3;
lt;
br {
true: { -- argsnum > 3
push arg[3];
push arg[2];
push arg[1];
push arg[0];
cextend 3;
ret;
}
false: { -- argsnum <= 2
push n;
push 2;
eq;
br {
true: { -- argsnum = 2
push arg[3];
push arg[2];
push arg[1];
push arg[0];
call $ 2;
tcall juvix_apply_1;
}
false: { -- argsnum = 1
push arg[3];
push arg[2];
push arg[1];
push arg[0];
call $ 1;
tcall juvix_apply_2;
}
};
}
};
}
};
};
}

function juvix_apply_4(*, *, *, *, *) : * {
push arg[0];
argsnum;
tsave n {
push n;
push 4;
eq;
br {
true: { -- argsnum = 4
push arg[4];
push arg[3];
push arg[2];
push arg[1];
push arg[0];
tcall $ 4;
}
false: {
push n;
push 4;
lt;
br {
true: { -- argsnum > 4
push arg[4];
push arg[3];
push arg[2];
push arg[1];
push arg[0];
cextend 4;
ret;
}
false: { -- argsnum <= 3
push n;
push 3;
eq;
br {
true: { -- argsnum = 3
push arg[4];
push arg[3];
push arg[2];
push arg[1];
push arg[0];
call $ 3;
tcall juvix_apply_1;
}
false: {
push n;
push 2;
eq;
br {
true: { -- argsnum = 2
push arg[4];
push arg[3];
push arg[2];
push arg[1];
push arg[0];
call $ 2;
tcall juvix_apply_2;
}
false: { -- argsnum = 1
push arg[4];
push arg[3];
push arg[2];
push arg[1];
push arg[0];
call $ 1;
tcall juvix_apply_3;
}
};
}
};
}
};
}
};
};
}
2 changes: 2 additions & 0 deletions runtime/src/juvix/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@
error_exit(); \
} while (0)

#define JUVIX_ARGS_NUM(var, val) (var = make_smallint(get_closure_largs(val)))

#define JUVIX_ALLOC_INT(var, val) (var = make_smallint(val))
// ALLOC_CONSTR_BOXED(var, uid, nargs)
// ALLOC_CONSTR_BOXED_TAG(var, uid)
Expand Down
8 changes: 5 additions & 3 deletions src/Juvix/Compiler/Asm/Data/InfoTableBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ emptyBuilderState =
}

runInfoTableBuilder :: Sem (InfoTableBuilder ': r) a -> Sem r (InfoTable, a)
runInfoTableBuilder =
fmap (first (^. stateInfoTable))
. runState emptyBuilderState
runInfoTableBuilder = fmap (first (^. stateInfoTable)) . runInfoTableBuilder' emptyBuilderState

runInfoTableBuilder' :: BuilderState -> Sem (InfoTableBuilder ': r) a -> Sem r (BuilderState, a)
runInfoTableBuilder' bs =
runState bs
. reinterpret interp
where
interp :: InfoTableBuilder m a -> Sem (State BuilderState ': r) a
Expand Down
60 changes: 60 additions & 0 deletions src/Juvix/Compiler/Asm/Extra/Apply.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module Juvix.Compiler.Asm.Extra.Apply where

import Data.FileEmbed qualified as FE
import Data.HashMap.Strict qualified as HashMap
import Data.Text.Encoding
import Juvix.Compiler.Asm.Data.InfoTable
import Juvix.Compiler.Asm.Data.InfoTableBuilder
import Juvix.Compiler.Asm.Language
import Juvix.Compiler.Asm.Translation.FromSource

data ApplyBuiltins = ApplyBuiltins
{ -- | The number of `juvix_apply_n` functions.
_applyBuiltinsNum :: Int,
-- | Maps `n` to the function `juvix_apply_n`.
_applyBuiltinsMap :: HashMap Int Symbol
}

makeLenses ''ApplyBuiltins

addApplyBuiltins :: InfoTable -> (ApplyBuiltins, InfoTable)
addApplyBuiltins tab = (blts, bs' ^. stateInfoTable)
where
nextSymbol = maximum (0 : HashMap.keys (tab ^. infoFunctions) ++ HashMap.keys (tab ^. infoInductives)) + 1
nextUserId = maximum (0 : mapMaybe getUserTag (HashMap.keys (tab ^. infoConstrs))) + 1

bs :: BuilderState
bs =
BuilderState
{ _stateNextSymbol = nextSymbol,
_stateNextUserTag = nextUserId,
_stateInfoTable = tab,
_stateIdents = mempty
}

bs' :: BuilderState
bs' =
fromRight impossible $
parseText' bs $
decodeUtf8 $(FE.makeRelativeToProject "runtime/src/asm/apply.jva" >>= FE.embedFile)

blts :: ApplyBuiltins
blts =
ApplyBuiltins
{ _applyBuiltinsNum = 4,
_applyBuiltinsMap =
HashMap.fromList $ map mkApply [1 .. 4]
}

mkApply :: Int -> (Int, Symbol)
mkApply x = (x, f)
where
idt = "juvix_apply_" <> show x
f = case fromJust $ HashMap.lookup idt (bs' ^. stateIdents) of
IdentFun s -> s
_ -> impossible

getUserTag :: Tag -> Maybe Word
getUserTag = \case
BuiltinTag {} -> Nothing
UserTag x -> Just x
9 changes: 9 additions & 0 deletions src/Juvix/Compiler/Asm/Extra/Recursors.hs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ recurse' sig = go True
return mem
Failure ->
return $ pushValueStack TyDynamic (popValueStack 1 mem)
ArgsNum -> do
when (null (mem ^. memoryValueStack)) $
throw $
AsmError loc "empty value stack"
checkFunType (topValueStack' 0 mem)
return $ pushValueStack mkTypeInteger (popValueStack 1 mem)
Prealloc {} ->
return mem
AllocConstr tag -> do
Expand Down Expand Up @@ -384,6 +390,9 @@ recurseS' sig = go
return si
Failure ->
return si
ArgsNum ->
-- push + pop = nop
return si
Prealloc {} ->
return si
AllocConstr tag -> do
Expand Down
8 changes: 8 additions & 0 deletions src/Juvix/Compiler/Asm/Interpreter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ runCodeR infoTable funInfo = goCode (funInfo ^. functionCode) >> popLastValueSta
Failure -> do
v <- topValueStack
runtimeError $ mappend "failure: " (printVal v)
ArgsNum -> do
v <- popValueStack
case v of
ValClosure cl -> do
let n = lookupFunInfo infoTable (cl ^. closureSymbol) ^. functionArgsNum - length (cl ^. closureArgs)
pushValueStack (ValInteger (toInteger n))
goCode cont
_ -> runtimeError "invalid operation: expected closure on top of value stack"
Prealloc {} ->
goCode cont
AllocConstr tag -> do
Expand Down
4 changes: 4 additions & 0 deletions src/Juvix/Compiler/Asm/Language.hs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ data Instruction
| -- | Interrupt execution with a runtime error printing the value on top of
-- the stack. JVA opcode: 'fail'.
Failure
| -- | Computes the number of expected arguments for the closure on top of the
-- stack, pops the stack and pushes the result on top of the stack. JVA
-- opcode: 'argsnum'.
ArgsNum
| -- | Preallocate memory. This instruction is inserted automatically before
-- translation to JuvixReg. It does not occur in JVA files.
Prealloc InstrPrealloc
Expand Down
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Asm/Pretty/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ instance PrettyCode Instruction where
Trace -> return $ primitive Str.instrTrace
Dump -> return $ primitive Str.instrDump
Failure -> return $ primitive Str.instrFailure
ArgsNum -> return $ primitive Str.instrArgsNum
Prealloc InstrPrealloc {..} ->
return $ primitive Str.instrPrealloc <+> integer _preallocWordsNum
AllocConstr tag -> (primitive Str.instrAlloc <+>) <$> ppConstrName tag
Expand Down
2 changes: 2 additions & 0 deletions src/Juvix/Compiler/Asm/Transformation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ module Juvix.Compiler.Asm.Transformation
( module Juvix.Compiler.Asm.Transformation.StackUsage,
module Juvix.Compiler.Asm.Transformation.Prealloc,
module Juvix.Compiler.Asm.Transformation.Validate,
module Juvix.Compiler.Asm.Transformation.Apply,
)
where

import Juvix.Compiler.Asm.Transformation.Apply
import Juvix.Compiler.Asm.Transformation.Prealloc
import Juvix.Compiler.Asm.Transformation.StackUsage
import Juvix.Compiler.Asm.Transformation.Validate
Loading
Loading