-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Filter out unreachable functions in JuvixAsm (#2575)
Adds a JuvixAsm transformation to filter out unreachable functions. This will make the generated nock/cairo code smaller.
- Loading branch information
Showing
12 changed files
with
247 additions
and
6 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
module Juvix.Compiler.Asm.Data.CallGraph where | ||
|
||
import Data.HashSet qualified as HashSet | ||
import Juvix.Compiler.Asm.Data.InfoTable | ||
import Juvix.Compiler.Asm.Extra | ||
import Juvix.Compiler.Asm.Language | ||
|
||
-- | Call graph type | ||
type CallGraph = DependencyInfo Symbol | ||
|
||
-- | Compute the call graph | ||
createCallGraph :: (Member (Error AsmError) r) => InfoTable -> Sem r CallGraph | ||
createCallGraph tab = do | ||
graph <- createCallGraphMap tab | ||
return $ createDependencyInfo graph startVertices | ||
where | ||
startVertices :: HashSet Symbol | ||
startVertices = HashSet.fromList syms | ||
|
||
syms :: [Symbol] | ||
syms = maybe [] singleton (tab ^. infoMainFunction) | ||
|
||
createCallGraphMap :: (Member (Error AsmError) r) => InfoTable -> Sem r (HashMap Symbol (HashSet Symbol)) | ||
createCallGraphMap tab = | ||
mapM | ||
(\FunctionInfo {..} -> getFunSymbols tab _functionCode) | ||
(tab ^. infoFunctions) | ||
|
||
getFunSymbols :: (Member (Error AsmError) r) => InfoTable -> Code -> Sem r (HashSet Symbol) | ||
getFunSymbols tab code = foldS sig code mempty | ||
where | ||
sig :: FoldSig StackInfo r (HashSet Symbol) | ||
sig = | ||
FoldSig | ||
{ _foldInfoTable = tab, | ||
_foldAdjust = const mempty, | ||
_foldInstr = \_ CmdInstr {..} acc -> return $ goInstr acc _cmdInstrInstruction, | ||
_foldBranch = \_ _ a1 a2 a3 -> return $ a1 <> a2 <> a3, | ||
_foldCase = \_ _ as ma a -> return $ mconcat as <> fromMaybe mempty ma <> a, | ||
_foldSave = \_ _ a1 a2 -> return $ a1 <> a2 | ||
} | ||
|
||
goInstr :: HashSet Symbol -> Instruction -> HashSet Symbol | ||
goInstr syms = \case | ||
AllocClosure InstrAllocClosure {..} -> HashSet.insert _allocClosureFunSymbol syms | ||
Call InstrCall {..} -> goCallType syms _callType | ||
TailCall InstrCall {..} -> goCallType syms _callType | ||
_ -> syms | ||
|
||
goCallType :: HashSet Symbol -> CallType -> HashSet Symbol | ||
goCallType syms = \case | ||
CallFun sym -> HashSet.insert sym syms | ||
CallClosure -> syms |
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
12 changes: 12 additions & 0 deletions
12
src/Juvix/Compiler/Asm/Transformation/FilterUnreachable.hs
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,12 @@ | ||
module Juvix.Compiler.Asm.Transformation.FilterUnreachable where | ||
|
||
import Data.HashMap.Strict qualified as HashMap | ||
import Juvix.Compiler.Asm.Data.CallGraph | ||
import Juvix.Compiler.Asm.Data.InfoTable | ||
import Juvix.Compiler.Asm.Error | ||
import Juvix.Compiler.Asm.Language | ||
|
||
filterUnreachable :: (Member (Error AsmError) r) => InfoTable -> Sem r InfoTable | ||
filterUnreachable tab = do | ||
graph <- createCallGraph tab | ||
return $ over infoFunctions (HashMap.filterWithKey (const . isReachable graph)) tab |
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,56 @@ | ||
module Asm.Transformation.Reachability (allTests) where | ||
|
||
import Asm.Run.Positive qualified as Run | ||
import Asm.Transformation.Base | ||
import Base | ||
import Data.HashMap.Strict qualified as HashMap | ||
import Juvix.Compiler.Asm.Options | ||
import Juvix.Compiler.Asm.Transformation | ||
import Juvix.Compiler.Asm.Transformation.Base | ||
|
||
data ReachabilityTest = ReachabilityTest | ||
{ _reachabilityTestReachable :: [Text], | ||
_reachabilityTestEval :: Run.PosTest | ||
} | ||
|
||
allTests :: TestTree | ||
allTests = | ||
testGroup "Reachability" $ | ||
map liftTest rtests | ||
|
||
rtests :: [ReachabilityTest] | ||
rtests = | ||
[ ReachabilityTest | ||
{ _reachabilityTestReachable = ["f", "f'", "g'", "h", "h'", "main"], | ||
_reachabilityTestEval = | ||
Run.PosTest | ||
"Test001: Reachability" | ||
$(mkRelDir "reachability") | ||
$(mkRelFile "test001.jva") | ||
$(mkRelFile "out/test001.out") | ||
}, | ||
ReachabilityTest | ||
{ _reachabilityTestReachable = ["f", "g", "id", "sum", "main"], | ||
_reachabilityTestEval = | ||
Run.PosTest | ||
"Test002: Reachability with loops & closures" | ||
$(mkRelDir "reachability") | ||
$(mkRelFile "test002.jva") | ||
$(mkRelFile "out/test002.out") | ||
} | ||
] | ||
|
||
liftTest :: ReachabilityTest -> TestTree | ||
liftTest ReachabilityTest {..} = | ||
fromTest | ||
Test | ||
{ _testTransformation = runTransformation (runReader opts . filterUnreachable), | ||
_testAssertion = \tab -> unless (nubSort (map (^. functionName) (HashMap.elems (tab ^. infoFunctions))) == nubSort _reachabilityTestReachable) (error "check reachable"), | ||
_testEval = _reachabilityTestEval | ||
} | ||
where | ||
opts = | ||
Options | ||
{ _optDebug = True, | ||
_optLimits = getLimits TargetCWasm32Wasi True | ||
} |
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 @@ | ||
9 |
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 @@ | ||
5051 |
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,44 @@ | ||
function h(integer) : integer { | ||
push arg[0]; | ||
ret; | ||
} | ||
|
||
function h'(integer) : integer { | ||
push arg[0]; | ||
ret; | ||
} | ||
|
||
function f(integer) : integer { | ||
push 1; | ||
push arg[0]; | ||
call h; | ||
add; | ||
ret; | ||
} | ||
|
||
function f'(integer) : integer { | ||
push 1; | ||
push arg[0]; | ||
call h'; | ||
add; | ||
ret; | ||
} | ||
|
||
function g(integer) : integer { | ||
push 2; | ||
push arg[0]; | ||
call f; | ||
add; | ||
ret; | ||
} | ||
|
||
function g'(integer) : integer { | ||
push arg[0]; | ||
tcall f'; | ||
} | ||
|
||
function main() : integer { | ||
push 7; | ||
call f; | ||
tcall g'; | ||
} |
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,58 @@ | ||
function f(*, integer) : integer { | ||
push arg[1]; | ||
push arg[0]; | ||
tcall $ 1; | ||
} | ||
|
||
function id(integer) : integer { | ||
push arg[0]; | ||
ret; | ||
} | ||
|
||
function g(integer) : integer { | ||
push 1; | ||
push arg[0]; | ||
calloc id 0; | ||
call f; | ||
add; | ||
ret; | ||
} | ||
|
||
function sum(integer) : integer { | ||
push arg[0]; | ||
push 0; | ||
eq; | ||
br { | ||
true: { | ||
push 0; | ||
tcall g; | ||
}; | ||
false: { | ||
push 1; | ||
push arg[0]; | ||
sub; | ||
call sum; | ||
push arg[0]; | ||
add; | ||
ret; | ||
}; | ||
}; | ||
} | ||
|
||
function g'(integer) : integer { | ||
push 2; | ||
push arg[0]; | ||
call id; | ||
add; | ||
ret; | ||
} | ||
|
||
function g''(integer) : integer { | ||
push arg[0]; | ||
tcall sum; | ||
} | ||
|
||
function main() : integer { | ||
push 100; | ||
tcall sum; | ||
} |