-
Notifications
You must be signed in to change notification settings - Fork 62
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
Toplevel rust translation #1905
Changes from 4 commits
951fb17
3b67591
82d34dd
c9c88b4
c7fe919
fb24c94
2a79212
72dbd3e
d204452
8326fc7
453b05e
56bfeac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// This file demonstrates how to use the `heapster_trans_rust_type` | ||
// command to translate rust signatures to heapster. | ||
enable_experimental; | ||
|
||
// Integer types This is wrong... we don't need an environment. | ||
env <- heapster_init_env_from_file "rust_data.sawcore" "rust_data.bc"; | ||
|
||
print "Define Rust types."; | ||
/*** | ||
*** Types | ||
***/ | ||
|
||
// Integer types | ||
heapster_define_perm env "int64" " " "llvmptr 64" "exists x:bv 64.eq(llvmword(x))"; | ||
heapster_define_perm env "int32" " " "llvmptr 32" "exists x:bv 32.eq(llvmword(x))"; | ||
heapster_define_perm env "int8" " " "llvmptr 8" "exists x:bv 8.eq(llvmword(x))"; | ||
heapster_define_perm env "int1" " " "llvmptr 1" "exists x:bv 1.eq(llvmword(x))"; | ||
|
||
heapster_define_llvmshape env "u64" 64 "" "fieldsh(int64<>)"; | ||
heapster_define_llvmshape env "u32" 64 "" "fieldsh(32,int32<>)"; | ||
heapster_define_llvmshape env "u8" 64 "" "fieldsh(8,int8<>)"; | ||
|
||
heapster_define_llvmshape env "usize" 64 "" "fieldsh(int64<>)"; | ||
heapster_define_llvmshape env "char" 64 "" "fieldsh(32,int32<>)"; | ||
|
||
// bool type | ||
heapster_define_llvmshape env "bool" 64 "" "fieldsh(1,int1<>)"; | ||
|
||
// Box type | ||
heapster_define_llvmshape env "Box" 64 "T:llvmshape 64" "ptrsh(T)"; | ||
|
||
// Result type | ||
heapster_define_rust_type env "pub enum Result<X,Y> { Ok (X), Err (Y) }"; | ||
|
||
// Infallable type | ||
heapster_define_llvmshape env "Infallible" 64 "" "falsesh"; | ||
|
||
// Sum type | ||
heapster_define_rust_type env "pub enum Sum<X,Y> { Left (X), Right (Y) }"; | ||
|
||
// The Option type | ||
heapster_define_rust_type env "pub enum Option<X> { None, Some (X) }"; | ||
|
||
|
||
print ""; | ||
print "-----------------------------------------------"; | ||
print "Translate 'unit'"; | ||
print "Rust: \n<> fn () -> ()"; | ||
print "Heapster:"; | ||
heapster_trans_rust_type env "<> fn () -> ()"; | ||
|
||
print ""; | ||
print "-----------------------------------------------"; | ||
print "Translate 'add'"; | ||
print "Rust: \n<> fn (x:u64, y:u64) -> u64"; | ||
print "Heapster:"; | ||
heapster_trans_rust_type env "<> fn (x:u64, y:u64) -> u64"; | ||
|
||
|
||
print ""; | ||
print "-----------------------------------------------"; | ||
print "Translate 'Ptr add'"; | ||
print "Rust: \n<'a,'b> fn (x:&'a u64, y:&'a u64) -> u64"; | ||
print "Heapster:"; | ||
heapster_trans_rust_type env "<'a,'b> fn (x:&'a u64, y:&'a u64) -> u64"; | ||
|
||
print ""; | ||
print "-----------------------------------------------"; | ||
print "Translate 'array length'"; | ||
print "Rust: \n<'a> fn (x:&'a [u64]) -> u64"; | ||
print "Heapster:"; | ||
heapster_trans_rust_type env "<'a> fn (x:&'a [u64]) -> u64"; | ||
|
||
|
||
print ""; | ||
print "-----------------------------------------------"; | ||
print "Translate 'add two array'"; | ||
print "Rust: \n<'a, 'b, 'c> fn (l1:&'a [u64], l2:&'b [u64]) -> &'c [u64]"; | ||
print "Heapster:"; | ||
heapster_trans_rust_type env "<'a, 'b, 'c> fn (l1:&'a [u64], l2:&'b [u64]) -> &'c [u64]"; | ||
|
||
print ""; | ||
print "-----------------------------------------------"; | ||
print "Translate 'add two array in place'"; | ||
print "Rust: \n<'a, 'b> fn (l1:&'a mut[u64], l2:&'b [u64]) -> ()"; | ||
print "Heapster:"; | ||
heapster_trans_rust_type env "<'a, 'b> fn (l1:&'a mut[u64], l2:&'b [u64]) -> ()"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1573,6 +1573,34 @@ parseFunPermFromRust env w args ret str | |
parseFunPermFromRust _ _ _ _ str = | ||
fail ("Malformed Rust type: " ++ str) | ||
|
||
|
||
-- | Just like `parseFunPermFromRust`, but doesn't take `args` and `ret`. | ||
-- usefull to translate rust when there is no LLVM module (e.g. from command line) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not that there is no LLVM module, it's that there is no specified LLVM function. Also, it seems like the only place where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. I removed the duplication and got it to typecheck. It looks right to me, but it's now doing Alternatively, I can make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, right, I didn't notice that |
||
parseSome3FunPermFromRust :: (Fail.MonadFail m, 1 <= w, KnownNat w) => | ||
PermEnv -> prx w -> | ||
String -> m Some3FunPerm | ||
parseSome3FunPermFromRust env w str | ||
| Just i <- findIndex (== '>') str | ||
, (gen_str, fn_str) <- splitAt (i+1) str | ||
, Right (Generics rust_ls1 rust_tvars wc span) <- | ||
parse (inputStreamFromString gen_str) | ||
, Right (BareFn _ abi rust_ls2 fn_tp _) <- | ||
parse (inputStreamFromString fn_str) = | ||
runLiftRustConvM (mkRustConvInfo env) $ | ||
rsConvertFun w abi (Generics (rust_ls1 ++ rust_ls2) rust_tvars wc span) fn_tp | ||
|
||
| Just i <- findIndex (== '>') str | ||
, (gen_str, _) <- splitAt (i+1) str | ||
, Left err <- parse @(Generics Span) (inputStreamFromString gen_str) = | ||
fail ("Error parsing generics: " ++ show err) | ||
|
||
| Just i <- findIndex (== '>') str | ||
, (_, fn_str) <- splitAt (i+1) str | ||
, Left err <- parse @(Ty Span) (inputStreamFromString fn_str) = | ||
fail ("Error parsing generics: " ++ show err) | ||
parseSome3FunPermFromRust _ _ str = | ||
fail ("Malformed Rust type: " ++ str) | ||
|
||
-- | Parse a polymorphic Rust type declaration and convert it to a Heapster | ||
-- shape | ||
-- Note: No CruCtx / TypeRepr as arguments for now | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ module SAWScript.HeapsterBuiltins | |
, heapster_find_trait_method_symbol | ||
, heapster_assume_fun | ||
, heapster_assume_fun_rename | ||
, heapster_translate_rust_type | ||
, heapster_assume_fun_rename_prim | ||
, heapster_assume_fun_multi | ||
, heapster_set_event_type | ||
|
@@ -124,6 +125,7 @@ import Verifier.SAW.Heapster.Permissions | |
import Verifier.SAW.Heapster.SAWTranslation | ||
import Verifier.SAW.Heapster.IRTTranslation | ||
import Verifier.SAW.Heapster.PermParser | ||
import Verifier.SAW.Heapster.RustTypes (parseSome3FunPermFromRust, Some3FunPerm(..)) | ||
import Verifier.SAW.Heapster.ParsedCtx | ||
import qualified Verifier.SAW.Heapster.IDESupport as HIDE | ||
import Verifier.SAW.Heapster.LLVMGlobalConst | ||
|
@@ -1020,7 +1022,7 @@ heapster_assume_fun_rename _bic _opts henv nm nm_to perms_string term_string = | |
do Some lm <- failOnNothing ("Could not find symbol: " ++ nm) | ||
(lookupModContainingSym henv nm) | ||
sc <- getSharedContext | ||
let w = llvmModuleArchReprWidth lm | ||
let w = llvmModuleArchReprWidth lm -- Should hardcode 64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't actually be hard coded to 64, since it could potentially be useful to have it match some other architecture with a different bit width. Currently, the way to achieve that is to specify it in the Heapster environment. I could imagine making this an argument instead of requiring a Heapster environment, but the current approach seems easiest for now, so maybe just remove this comment? |
||
leq_proof <- case decideLeq (knownNat @1) w of | ||
Left pf -> return pf | ||
Right _ -> fail "LLVM arch width is 0!" | ||
|
@@ -1040,6 +1042,23 @@ heapster_assume_fun_rename _bic _opts henv nm nm_to perms_string term_string = | |
(globalOpenTerm term_ident) | ||
liftIO $ writeIORef (heapsterEnvPermEnvRef henv) env'' | ||
|
||
heapster_translate_rust_type :: BuiltinContext -> Options -> HeapsterEnv -> | ||
String -> TopLevel () | ||
heapster_translate_rust_type _bic _opts henv perms_string = | ||
do env <- liftIO $ readIORef $ heapsterEnvPermEnvRef henv | ||
let w64 = (knownNat @64::NatRepr 64) | ||
leq_proof <- case decideLeq (knownNat @1) w64 of | ||
Left pf -> return pf | ||
Right _ -> fail "LLVM arch width is 0!" | ||
withKnownNat w64 $ withLeqProof leq_proof $ do | ||
Some3FunPerm fun_perm <- | ||
parseSome3FunPermFromRust env w64 perms_string | ||
--parseFunPermStringMaybeRust "permissions" w64 env args ret perms_string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove this commented out line from the code |
||
liftIO $ putStrLn $ permPrettyString emptyPPInfo fun_perm | ||
|
||
-- Lookup a how to print to io & and, looking into permissions.hs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove these comments from the code |
||
-- for permPrettyString and pass an empty ppInfo to print 'fun_perm' | ||
|
||
-- | Create a new SAW core primitive named @nm@ with type @tp@ in the module | ||
-- associated with the supplied Heapster environment, and return its identifier | ||
insPrimitive :: HeapsterEnv -> String -> Term -> TopLevel Ident | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4253,11 +4253,18 @@ primitives = Map.fromList | |
[ "Tell Heapster whether to perform its translation-time checks of the " | ||
, "well-formedness of type-checking proofs" ] | ||
|
||
, prim "heapster_trans_rust_type" | ||
"HeapsterEnv -> String -> TopLevel ()" | ||
(bicVal heapster_translate_rust_type) | ||
Experimental | ||
[ "Parse and print back a set of Heapster permissions for a function" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like this description is slightly imprecise in a way that might confuse the user, because it sounds like the function is parsing Heapster permissions and printing them. The point of this function is to convert a Rust type to a Heapster type and print out the result. So maybe say something like that. |
||
] | ||
|
||
, prim "heapster_parse_test" | ||
"LLVMModule -> String -> String -> TopLevel ()" | ||
(bicVal heapster_parse_test) | ||
Experimental | ||
[ "Parse and print back a set of Heapster permissions for a function" | ||
[ "Parse the Rust signature for a function and print the equivalent Heapser type. Ideal for learning how Rust types are translated into Heapster. " | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ohh, it looks like the doc string for |
||
] | ||
|
||
, prim "heapster_dump_ide_info" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't leave these comments in the code.