summaryrefslogtreecommitdiff
path: root/compiler/PrePasses.ml
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/PrePasses.ml')
-rw-r--r--compiler/PrePasses.ml54
1 files changed, 54 insertions, 0 deletions
diff --git a/compiler/PrePasses.ml b/compiler/PrePasses.ml
new file mode 100644
index 00000000..a09ae476
--- /dev/null
+++ b/compiler/PrePasses.ml
@@ -0,0 +1,54 @@
+(** This files contains passes we apply on the AST *before* calling the
+ (concrete/symbolic) interpreter on it
+ *)
+
+module T = Types
+module V = Values
+module E = Expressions
+module C = Contexts
+module A = LlbcAst
+module L = Logging
+
+let log = L.pre_passes_log
+
+(** Rustc inserts a lot of drops before the assignments.
+ We consider those drops are part of the assignment, and splitting the
+ drop and the assignment is problematic for us because it can introduce
+ [⊥] under borrows. For instance, we encountered situations like the
+ following one:
+
+ {[
+ drop( *x ); // Illegal! Inserts a ⊥ under a borrow
+ *x = move ...;
+ ]}
+
+ TODO: this is not necessary anymore
+ *)
+let filter_drop_assigns (f : A.fun_decl) : A.fun_decl =
+ (* The visitor *)
+ let obj =
+ object (self)
+ inherit [_] A.map_statement as super
+
+ method! visit_Sequence env st1 st2 =
+ match (st1.content, st2.content) with
+ | Drop p1, Assign (p2, _) ->
+ if p1 = p2 then (self#visit_statement env st2).content
+ else super#visit_Sequence env st1 st2
+ | Drop p1, Sequence ({ content = Assign (p2, _); meta = _ }, _) ->
+ if p1 = p2 then (self#visit_statement env st2).content
+ else super#visit_Sequence env st1 st2
+ | _ -> super#visit_Sequence env st1 st2
+ end
+ in
+ (* Map *)
+ let body =
+ match f.body with
+ | Some body -> Some { body with body = obj#visit_statement () body.body }
+ | None -> None
+ in
+ { f with body }
+
+let apply_passes (m : Crates.llbc_crate) : Crates.llbc_crate =
+ let functions = List.map filter_drop_assigns m.functions in
+ { m with functions }