From 9339c414770044cd477815f1cdadd40d0da5a9ba Mon Sep 17 00:00:00 2001
From: Kostyantyn Vorobyov <kostyantyn.vorobyov@cea.fr>
Date: Fri, 19 May 2017 13:38:02 +0200
Subject: [PATCH] Aligning small blocks during temporal analysis

---
 src/plugins/e-acsl/prepare_ast.ml | 55 +++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/src/plugins/e-acsl/prepare_ast.ml b/src/plugins/e-acsl/prepare_ast.ml
index cece0929519..980326a32fb 100644
--- a/src/plugins/e-acsl/prepare_ast.ml
+++ b/src/plugins/e-acsl/prepare_ast.ml
@@ -22,9 +22,64 @@
 
 open Cil_types
 
+exception Alignment_error of string
+let align_error s = raise (Alignment_error s)
+
+(* Returns true if the list of attributes [attrs] contains an [align]
+ * attribute of [algn] or greater. Returns false otherwise.
+ * Throws an exception if
+ *  - [attrs] contains several [align] attributes specifying different
+ *    alignment
+ *  - [attrs] has a single align attribute with a value which is less than [algn] *)
+let sufficiently_aligned attrs algn =
+  let alignment = List.fold_left (fun acc attr ->
+    match attr with
+    | Attr("align", [AInt i]) ->
+      let alignment = Integer.to_int i in
+      if acc <> 0 && acc <> alignment then
+        (* Multiple align attributes with different values *)
+        align_error "Multiple alignment attributes"
+      else if alignment < algn then
+        (* If there is an alignment attribute it should be greater
+          * or equal to [algn] *)
+        align_error "Insufficient alignment"
+      else
+        alignment
+    | Attr("align", _) ->
+      (* Align attribute with an argument other than a single number,
+      should not happen really *)
+      assert false
+    | _ -> acc
+  ) 0 attrs in
+  if alignment > 0 then true else false
+
+(* Given the type and the list of attributes of [varinfo] ([fieldinfo]) return
+ * true if that [varinfo] ([fieldinfo]) requires to be aligned at the boundary
+ * of [algn] (i.e., less than [algn] bytes and has no alignment attribute *)
+let require_alignment typ attrs algn =
+  if (Cil.bitsSizeOf typ) < algn*8 && not (sufficiently_aligned attrs algn) then
+    true
+  else
+    false
+
 class prepare_visitor prj = object (_)
   inherit Visitor.frama_c_copy prj
 
+  (* Add align attributes to local variables (required by temporal analysis) *)
+  method !vblock _ =
+    if (Temporal.is_enabled ()) then
+      Cil.DoChildrenPost (fun blk ->
+        List.iter (fun vi ->
+          if require_alignment vi.vtype vi.vattr 4; then begin
+            vi.vattr <- Attr("aligned",[AInt(Integer.four)]) :: vi.vattr
+          end)
+        blk.blocals;
+      blk)
+    else
+      Cil.DoChildren
+
+  (* Move variable declared in the body of a switch statement to the outer
+     scope *)
   method !vstmt_aux _ =
     Cil.DoChildrenPost (fun stmt ->
       match stmt.skind with
-- 
GitLab