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

MIR enums #1991

Merged
merged 1 commit into from Dec 15, 2023
Merged

MIR enums #1991

merged 1 commit into from Dec 15, 2023

Conversation

RyanGlScott
Copy link
Contributor

@RyanGlScott RyanGlScott commented Nov 27, 2023

This adds basic support for enums in the MIR backend. In particular:

  • There is now a mir_enum_value : MIRAdt -> String -> [MIRValue] -> MIRValue function that constructs a value representing a specific enum variant, where the String indicates which variant to use.
  • The mir_fresh_expanded_value command can now create symbolic enum values.

Implementation-wise, much of the complexity in this patch arises from the fact that MIR enums are represented with VariantTypes at the Crucible level, which are a fair bit more involved than the StructTypes used to power MIR structs. Some highlights of the implementation are:

  • There is now a new EnumShape constructor for TypeShape, which is in turn defined in terms of a new VariantShape data type that characterizes the shapes of all the fields in an enum variant.
  • There is a MirSetupEnum data type (exported by SAWScript.Crucible.MIR.MethodSpecIR) which categorizes the different forms of enum MIRValues that one can construct. Currently, there is MirSetupEnumVariant (which is what mir_enum_value returns) and MirSetupEnumSymbolic (which is what mir_fresh_expanded_value returns when it creates a fresh enum value).
  • The implementation of symbolic enum values in particular is somewhat complicated. I have written Note [Symbolic enums] to go over the general approach and highlight some potential pitfalls in implementing them.
  • For now, there is no crux-mir-comp support for enums. We could conceivable add support, but there is not a pressing need to do so right now. I have opened crux-mir-comp: Support enums #1990 as a reminder to do this later.

This checks off one box in #1859.

doc/manual/manual.md Outdated Show resolved Hide resolved
@@ -742,6 +751,8 @@ regToSetup bak p eval shp rv = go shp rv
refSV <- go refShp refRV
lenSV <- go lenShp lenRV
pure $ MS.SetupSlice $ MirSetupSliceRaw refSV lenSV
go (EnumShape _ _ _ _ _) _ =
error "Enums not currently supported in overrides"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #1990 for the task of supporting enums in {crucible,crux}-mir-comp.

Comment on lines +103 to +117
-- | A shape for an enum type. Like 'StructShape', this is indexed by
-- 'AnyType', so code that matches on 'EnumShape' may need to further match
-- on the 'VariantShape's in order to bring additional type information into
-- scope.
EnumShape :: M.Ty
-- ^ The overall enum type.
-> [[M.Ty]]
-- ^ The field types in each of the enum's variants.
-> Assignment VariantShape ctx
-- ^ The shapes of the enum type's variants.
-> M.Ty
-- ^ The discriminant type.
-> TypeShape discrTp
-- ^ The shape of the discriminant type.
-> TypeShape AnyType
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a new TypeShape constructor that is used extensively in this patch...

Comment on lines +144 to +154
-- | The 'TypeShape' of an enum variant, which consists of some number of field
-- types.
--
-- This is indexed by a 'StructType', but that is simply an artifact of the
-- particular way that @crucible-mir@ encodes enum types. Despite the use of
-- 'StructType' as a type index, we only use 'VariantShape' for enums, not
-- structs.
data VariantShape (tp :: CrucibleType) where
VariantShape :: Assignment FieldShape ctx
-- ^ The shapes of the variant's field types.
-> VariantShape (StructType ctx)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...as well as the related VariantShape data type.

Comment on lines +148 to +149
-- | A enum-related MIR 'SetupValue'.
data MirSetupEnum where
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This data type classifies the two ways that one can create an enum value (either via mir_enum_value or mir_fresh_expanded_value).

@@ -157,3 +229,137 @@ data MirSetupSlice
makeLenses ''MIRCrucibleContext
makeLenses ''MirAllocSpec
makeLenses ''MirPointer

{-
Note [Symbolic enums]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A large piece of documentation that I wrote about the approach to handling symbolic enum values.

[ "Expected struct type, received union:"
, show nm
]
MS.SetupEnum enum_ ->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implements turning a SetupEnum into a value that Crucible can reason about. (It's quite involved, sadly—sorry.)

Comment on lines +1105 to +1114
-- In order to match an enum value, we first check to see if the expected
-- value is a specific enum variant or a symbolic enum...
(MIRVal (EnumShape _ _ variantShps _ discrShp)
(Crucible.AnyValue
(Mir.RustEnumRepr discrTpr variantCtx)
(Ctx.Empty
Ctx.:> Crucible.RV actualDiscr
Ctx.:> Crucible.RV variantAssn)),
_,
MS.SetupEnum enum_)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implements matching one enum value against another.

Comment on lines 387 to 398
-- Create a fresh symbolic enum value, as described in
-- Note [Symboliic enums] in SAWScript.Crucible.MIR.Setup.Value.
goEnum ::
forall discrShp variantCtx.
Text ->
Mir.Adt ->
TypeShape discrShp ->
Ctx.Assignment VariantShape variantCtx ->
CrucibleSetup MIR MirSetupEnum
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generates all of the symbolic variables used in a symbolic enum value.

constructing a struct value), and `mir_enum_value` (for constructing an enum
value) commands in turn take a `MIRAdt` as an argument.

#### Enums
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation about enums.

Copy link
Contributor

@spernsteiner spernsteiner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - just a few typos and minor comments

doc/manual/manual.md Outdated Show resolved Hide resolved
doc/manual/manual.md Outdated Show resolved Hide resolved
src/SAWScript/Crucible/MIR/Builtins.hs Outdated Show resolved Hide resolved
src/SAWScript/Crucible/MIR/Builtins.hs Show resolved Hide resolved
src/SAWScript/Crucible/MIR/Override.hs Outdated Show resolved Hide resolved
src/SAWScript/Crucible/MIR/Override.hs Outdated Show resolved Hide resolved
src/SAWScript/Crucible/MIR/ResolveSetupValue.hs Outdated Show resolved Hide resolved
This adds basic support for enums in the MIR backend. In particular:

* There is now a `mir_enum_value : MIRAdt -> String -> [MIRValue] -> MIRValue`
  function that constructs a value representing a specific enum variant, where
  the `String` indicates which variant to use.
* The `mir_fresh_expanded_value` command can now create symbolic enum values.

Implementation-wise, much of the complexity in this patch arises from the fact
that MIR enums are represented with `VariantType`s at the Crucible level, which
are a fair bit more involved than the `StructType`s used to power MIR structs.
Some highlights of the implementation are:

* There is now a new `EnumShape` constructor for `TypeShape`, which is in turn
  defined in terms of a new `VariantShape` data type that characterizes the
  shapes of all the fields in an enum variant.
* There is a `MirSetupEnum` data type (exported by
  `SAWScript.Crucible.MIR.MethodSpecIR`) which categorizes the different forms
  of enum `MIRValue`s that one can construct. Currently, there is
  `MirSetupEnumVariant` (which is what `mir_enum_value` returns) and
  `MirSetupEnumSymbolic` (which is what `mir_fresh_expanded_value` returns
  when it creates a fresh enum value).
* The implementation of symbolic enum values in particular is somewhat
  complicated. I have written `Note [Symbolic enums]` to go over the general
  approach and highlight some potential pitfalls in implementing them.
* For now, there is no `crux-mir-comp` support for enums. We could conceivable
  add support, but there is not a pressing need to do so right now. I have
  opened #1990 as a reminder to
  do this later.

This checks off one box in #1859.
@RyanGlScott RyanGlScott added the ready-to-merge If at least one person approves this PR, automatically merge it when CI finishes successfully. label Dec 15, 2023
@mergify mergify bot merged commit 63093c3 into master Dec 15, 2023
40 checks passed
@mergify mergify bot deleted the T1859-mir_enums branch December 15, 2023 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-to-merge If at least one person approves this PR, automatically merge it when CI finishes successfully.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants