Allow more MIR types to be "flexibly" embedded into Cryptol #1976
Labels
missing cryptol features
Issues about features in Cryptol that don't work in SAW
subsystem: crucible-llvm
Issues related to LLVM bitcode verification with crucible-llvm
subsystem: crucible-mir
Issues related to Rust verification with crucible-mir and/or mir-json
type: enhancement
Issues describing an improvement to an existing feature or capability
Milestone
Currently, the SAW MIR backend suffers from some notable drawbacks:
u32
andi32
type are mapped to[32]
in Cryptol, but when mapping[32]
from Cryptol back into MIR (e.g., through themir_term
command), we arbitrarily choose to convert it tou32
, noti32
. (And similarly for all other primitive integral types.) To prevent this from being overly burdensome, we relax the type equality judgment in the MIR backend such thatu32
andi32
are deemed to be equal types (see thecheckCompatibleTys
function), but this runs the risk of accepting ill-typed SAW specifications.Issue (1) is mildly annoying, but issue (2) is very annoying, as it prevents certain classes of Rust functions from having elegant SAW specifications. For instance, anything involving the
Wrapping
type (a struct) becomes very tedious to write, which is made worse by the fact thatWrapping
is used a lot in the broader Rust ecosystem.Both of these issues ultimately have the same root cause: MIR's type system is richer than Cryptol's type system, and as a result, there are some MIR types that cannot be represented in Cryptol without necessarily losing some information. For instance, given this code:
Then we could envision mapping the
S1
struct to the Cryptol record type{ x : [32], y : [64] }
. However, we could just as well mapS2
to the same type. Therefore, what MIR type should we get if we writemir_term {{ _ : { x : [32], y : [64] } }}
? Should we getS1
?S2
? Another struct? The answer was unclear to me when I first designed the SAW MIR backend, so I ultimately excluded MIR structs from being mapped into Cryptol. However, feedback suggests that this restriction goes to far, so we should consider how to make something like this possible.My proposal: we make SAW's dynamic typing more "flexible". That is, when you write
mir_term {{ _ : { x : [32], y : [64] } }}
, it should be able to representS1
,S2
, or any other struct with compatible field types depending on the context it is used. This would be a departure from established SAW conventions, as SAW currently expects all SAWScript expressions to have a single, unambiguous type. (See thetypeOfSetupValue
function.) But I think changing the conventions here would be worthwhile, as it would make the SAW<->Cryptol interoperability story much nicer.To spell things out in a little more detail:
u<N>
andi<N>
would continue to map to the Cryptol[<N>]
type as they do currently. The Cryptol[<N>]
type could map tou<N>
ori<N>
depending on the surrounding context it is used.Wrapping<ty>
, they would map to the same Cryptol type that<ty>
does. The resulting Cryptol type could then map back to any number of MIR types that have the same field names and types.This proposed refactoring would primarily benefit the MIR backend, but it would also benefit the LLVM backend. For instance, LLVM has both unpacked struct types (e.g.,
{ u32, u64 }
) and unpacked struct types (e.g.,<{ u32, u64 }>
), but this distinction is lost when we map it into a Cryptol tuple in SAW (we map all Cryptol tuples back to unpacked structs in LLVM). Using the "flexible" typing discipline described above, we could allow SAW specifications involving both unpacked and packed structs alike.The text was updated successfully, but these errors were encountered: