forked from GaloisInc/cryptol
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
177 lines (160 loc) · 6.49 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
-- |
-- Module : Main
-- Copyright : (c) 2015-2016 Galois, Inc.
-- License : BSD3
-- Maintainer : [email protected]
-- Stability : provisional
-- Portability : portable
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.DeepSeq ( force )
import Control.Monad.IO.Class( liftIO )
import qualified Data.Text as T
import qualified Data.Text.IO as T
import System.FilePath ((</>))
import qualified System.Directory as Dir
import qualified Cryptol.Eval as E
import qualified Cryptol.Eval.Value as E
import qualified Cryptol.Eval.Concrete as C
import qualified Cryptol.ModuleSystem.Base as M
import qualified Cryptol.ModuleSystem.Env as M
import qualified Cryptol.ModuleSystem.Monad as M
import qualified Cryptol.ModuleSystem.NamingEnv as M
import Cryptol.ModuleSystem.Interface (noIfaceParams)
import qualified Cryptol.Parser as P
import qualified Cryptol.Parser.AST as P
import qualified Cryptol.Parser.NoInclude as P
import qualified Cryptol.Eval.SBV as S
import qualified Cryptol.TypeCheck as T
import qualified Cryptol.TypeCheck.AST as T
import qualified Cryptol.Utils.Ident as I
import Cryptol.Utils.Logger(quietLogger)
import qualified Data.SBV.Dynamic as SBV
import Criterion.Main
main :: IO ()
main = do
cd <- Dir.getCurrentDirectory
defaultMain [
bgroup "parser" [
parser "Prelude" "lib/Cryptol.cry"
, parser "BigSequence" "bench/data/BigSequence.cry"
, parser "BigSequenceHex" "bench/data/BigSequenceHex.cry"
, parser "AES" "bench/data/AES.cry"
, parser "SHA512" "bench/data/SHA512.cry"
]
, bgroup "typechecker" [
tc cd "Prelude" "lib/Cryptol.cry"
, tc cd "BigSequence" "bench/data/BigSequence.cry"
, tc cd "BigSequenceHex" "bench/data/BigSequenceHex.cry"
, tc cd "AES" "bench/data/AES.cry"
, tc cd "SHA512" "bench/data/SHA512.cry"
]
, bgroup "conc_eval" [
ceval cd "AES" "bench/data/AES.cry" "bench_correct"
, ceval cd "ZUC" "bench/data/ZUC.cry" "ZUC_TestVectors"
, ceval cd "SHA512" "bench/data/SHA512.cry" "testVector1 ()"
]
, bgroup "sym_eval" [
seval cd "AES" "bench/data/AES.cry" "bench_correct"
, seval cd "ZUC" "bench/data/ZUC.cry" "ZUC_TestVectors"
, seval cd "SHA512" "bench/data/SHA512.cry" "testVector1 ()"
]
]
-- | Evaluation options, mostly used by `trace`.
-- Since the benchmarks likely do not use base, these don't matter very much
evOpts :: E.EvalOpts
evOpts = E.EvalOpts { E.evalLogger = quietLogger
, E.evalPPOpts = E.defaultPPOpts
}
-- | Make a benchmark for parsing a Cryptol module
parser :: String -> FilePath -> Benchmark
parser name path =
env (T.readFile path) $ \(~bytes) ->
bench name $ nfIO $ do
let cfg = P.defaultConfig
{ P.cfgSource = path
, P.cfgPreProc = P.guessPreProc path
}
case P.parseModule cfg bytes of
Right pm -> return pm
Left err -> error (show err)
-- | Make a benchmark for typechecking a Cryptol module. Does parsing
-- in the setup phase in order to isolate typechecking
tc :: String -> String -> FilePath -> Benchmark
tc cd name path =
let withLib = M.withPrependedSearchPath [cd </> "lib"] in
let setup = do
bytes <- T.readFile path
let cfg = P.defaultConfig
{ P.cfgSource = path
, P.cfgPreProc = P.guessPreProc path
}
Right pm = P.parseModule cfg bytes
menv <- M.initialModuleEnv
(eres, _) <- M.runModuleM (evOpts,menv) $ withLib $ do
-- code from `loadModule` and `checkModule` in
-- `Cryptol.ModuleSystem.Base`
let pm' = M.addPrelude pm
M.loadDeps pm'
enim <- M.io (P.removeIncludesModule path pm')
nim <- either (error "Failed to remove includes") return enim
npm <- M.noPat nim
(tcEnv,declsEnv,scm) <- M.renameModule npm
prims <- if P.thing (P.mName pm) == I.preludeName
then return (M.toPrimMap declsEnv)
else M.getPrimMap
return (prims, scm, tcEnv)
case eres of
Right ((prims, scm, tcEnv), menv') ->
return (prims, scm, tcEnv, menv')
Left _ -> error $ "Failed to load " ++ name
in env setup $ \ ~(prims, scm, tcEnv, menv) ->
bench name $ whnfIO $ M.runModuleM (evOpts,menv) $ withLib $ do
let act = M.TCAction { M.tcAction = T.tcModule
, M.tcLinter = M.moduleLinter (P.thing (P.mName scm))
, M.tcPrims = prims
}
M.typecheck act scm noIfaceParams tcEnv
ceval :: String -> String -> FilePath -> T.Text -> Benchmark
ceval cd name path expr =
let withLib = M.withPrependedSearchPath [cd </> "lib"] in
let setup = do
menv <- M.initialModuleEnv
(eres, _) <- M.runModuleM (evOpts,menv) $ withLib $ do
m <- M.loadModuleByPath path
M.setFocusedModule (T.mName m)
let Right pexpr = P.parseExpr expr
(_, texpr, _) <- M.checkExpr pexpr
return texpr
case eres of
Right (texpr, menv') -> return (texpr, menv')
Left _ -> error $ "Failed to load " ++ name
in env setup $ \ ~(texpr, menv) ->
bench name $ nfIO $ E.runEval evOpts $ do
let ?evalPrim = C.evalPrim
env' <- E.evalDecls C.Concrete (M.allDeclGroups menv) mempty
(e :: C.Value) <- E.evalExpr C.Concrete env' texpr
E.forceValue e
seval :: String -> String -> FilePath -> T.Text -> Benchmark
seval cd name path expr =
let withLib = M.withPrependedSearchPath [cd </> "lib"] in
let setup = do
menv <- M.initialModuleEnv
(eres, _) <- M.runModuleM (evOpts,menv) $ withLib $ do
m <- M.loadModuleByPath path
M.setFocusedModule (T.mName m)
let Right pexpr = P.parseExpr expr
(_, texpr, _) <- M.checkExpr pexpr
return texpr
case eres of
Right (texpr, menv') -> return (texpr, menv')
Left _ -> error $ "Failed to load " ++ name
in env setup $ \ ~(texpr, menv) ->
bench name $ whnfIO $ fmap force E.runEval evOpts $ S.sbvEval $ do
let ?evalPrim = S.evalPrim
env' <- E.evalDecls S.SBV (M.allDeclGroups menv) mempty
(e :: S.Value) <- E.evalExpr S.SBV env' texpr
liftIO $ SBV.generateSMTBenchmark False $
return (E.fromVBit e)