diff --git a/src/dune b/src/dune
index 599d3f7423ac6a0e1daba6de1ea8c204345e76e3..7cd55aa0b825af3628b942e63f2e0b5503c955a6 100644
--- a/src/dune
+++ b/src/dune
@@ -39,6 +39,7 @@
           (echo "  - dune-site.plugins:" %{lib-available:dune-site.plugins} "\n")
           (echo "  - ppx_import:" %{lib-available:ppx_import} "\n")
           (echo "  - ppx_deriving.eq:" %{lib-available:ppx_deriving.eq} "\n")
+          (echo "  - ppx_deriving.ord:" %{lib-available:ppx_deriving.ord} "\n")
           (echo "  - ppx_deriving_yaml:" %{lib-available:ppx_deriving_yaml} "\n")
   )
   )
@@ -51,7 +52,7 @@
   (flags :standard -w -9)
   (libraries frama-c.init fpath str unix zarith ocamlgraph dynlink bytes yaml.unix yojson menhirLib dune-site dune-site.plugins)
   (instrumentation (backend landmarks))
-  (preprocess (staged_pps ppx_import ppx_deriving.eq ppx_deriving_yaml))
+  (preprocess (staged_pps ppx_import ppx_deriving.eq ppx_deriving.ord ppx_deriving_yaml))
 )
 
 (generate_sites_module (module config_data) (sites frama-c) (plugins (frama-c plugins) (frama-c plugins_gui)))
diff --git a/src/kernel_services/abstract_interp/eva_types.ml b/src/kernel_services/abstract_interp/eva_types.ml
index 4e4c5c835587809ba6c80e16eb03b389d581533e..de54d6beef06179e7628d41342b308561fe4becd 100644
--- a/src/kernel_services/abstract_interp/eva_types.ml
+++ b/src/kernel_services/abstract_interp/eva_types.ml
@@ -25,31 +25,27 @@ struct
   module Thread = Int (* Threads are identified by integers *)
   module Kf = Kernel_function
   module Stmt = Cil_datatype.Stmt
-
-  type call = Cil_types.kernel_function * Cil_types.stmt
+  module Var = Cil_datatype.Varinfo
 
   module Call = Datatype.Pair_with_collections(Kf)(Stmt)
       (struct let module_name = "Eva.Callstack.Call" end)
 
-
   module Calls = Datatype.List (Call)
 
-  type callstack = {
+  type local_stack = {
     thread: int;
-    entry_point: Cil_types.kernel_function;
-    stack: call list;
+    entry_point: Kernel_function.t;
+    stack: Call.t list;
   }
 
-
-  (* Datatype *)
-
-  module Prototype =
+  module LocalStack =
   struct
-    include Datatype.Serializable_undefined
-
-    type t = callstack
-
-    let name = "Eva.Callstack"
+    type t = local_stack = {
+      thread: int;
+      entry_point: Kernel_function.t;
+      stack: Call.t list;
+    }
+    [@@deriving eq, ord]
 
     let reprs =
       List.concat_map (fun stack ->
@@ -65,22 +61,46 @@ struct
       in
       Format.fprintf fmt "@[<hv>";
       List.iter (pp_call fmt) cs.stack;
-      Format.fprintf fmt "%a@]" Kf.pretty cs.entry_point
+      Format.fprintf fmt "%a@]" Kernel_function.pretty cs.entry_point
+
+    let hash cs =
+      Hashtbl.hash
+        (cs.thread, Kernel_function.hash cs.entry_point, Calls.hash cs.stack)
+  end
+
+  type call = Call.t
 
-    let equal cs1 cs2 =
-      Thread.equal cs1.thread cs2.thread &&
-      Calls.equal cs1.stack cs2.stack &&
-      Kf.equal cs1.entry_point cs2.entry_point
+  type callstack =
+    | Global of Cil_datatype.Varinfo.t
+    | Local of LocalStack.t
 
-    let compare cs1 cs2 =
-      let r = Thread.compare cs1.thread cs2.thread in
-      if r <> 0 then r else
-        let r = Kf.compare cs1.entry_point cs2.entry_point in
-        if r <> 0 then r else
-          Calls.compare cs1.stack cs2.stack
+  (* Datatype *)
+
+  module Prototype =
+  struct
+    open Cil_datatype
+    include Datatype.Serializable_undefined
+
+    type t = callstack =
+      | Global of Varinfo.t
+      | Local of LocalStack.t
+    [@@deriving eq, ord]
+
+    let name = "Eva.Callstack"
+
+    let reprs =
+      List.map (fun vi -> Global vi) Varinfo.reprs @
+      List.map (fun ls -> Local ls) LocalStack.reprs
+
+    let pretty fmt cs =
+      match cs with
+      | Global vi -> Format.fprintf fmt "init %a" Varinfo.pretty vi
+      | Local ls -> LocalStack.pretty fmt ls
 
     let hash cs =
-      Hashtbl.hash (cs.thread, Kf.hash cs.entry_point, Calls.hash cs.stack)
+      match cs with
+      | Global vi -> Hashtbl.hash (1, Varinfo.hash vi)
+      | Local ls -> Hashtbl.hash (2, LocalStack.hash ls)
   end
 
   include Datatype.Make_with_collections (Prototype)
@@ -88,50 +108,86 @@ struct
 
   (* Constructor *)
 
-  let init ?(thread=0) entry_point = { thread ; entry_point ; stack = [] }
+  let init_global vi =
+    Global vi
+
+  let init_local ?(thread=0) kf =
+    Local { thread; entry_point=kf; stack = [] }
+
+  (* Query *)
 
+  let is_local = function
+    | Global _ -> false
+    | Local _ -> true
 
   (* Stack manipulation *)
 
+  let local = function
+    | Global _vi ->
+      invalid_arg "invalid stack manipulation on a global callstack"
+    | Local ls -> ls
+
   let push kf stmt cs =
-    { cs with stack = (kf, stmt) :: cs.stack }
+    let ls = local cs in
+    Local { ls with stack = (kf, stmt) :: ls.stack }
 
   let pop cs =
-    match cs.stack with
-    | [] -> None
-    | (kf,stmt) :: tail -> Some (kf, stmt, { cs with stack = tail })
+    match cs with
+    | Global _vi -> None
+    | Local ls ->
+      match ls.stack with
+      | [] -> None
+      | (kf,stmt) :: tail -> Some (kf, stmt, Local { ls with stack = tail })
 
   let top cs =
-    match cs.stack with
-    | [] -> None
-    | (kf, stmt) :: _ -> Some (kf, stmt)
+    match cs with
+    | Global _vi -> None
+    | Local ls ->
+      match ls.stack with
+      | [] -> None
+      | (kf, stmt) :: _ -> Some (kf, stmt)
 
   let top_kf cs =
-    match cs.stack with
-    | [] -> cs.entry_point
+    let ls = local cs in
+    match ls.stack with
     | (kf, _stmt) :: _ -> kf
+    | [] -> ls.entry_point
 
   let top_callsite cs =
-    match cs.stack with
-    | [] -> None
-    | (_kf, stmt) :: _ -> Some (stmt)
+    match cs with
+    | Global _vi -> None
+    | Local ls ->
+      match ls.stack with
+      | [] -> None
+      | (_kf, stmt) :: _ -> Some (stmt)
 
   let top_call cs =
-    match cs.stack with
-    | [] -> cs.entry_point, Cil_types.Kglobal
+    let ls = local cs in
+    match ls.stack with
     | (kf, stmt) :: _ -> kf, Cil_types.Kstmt stmt
+    | [] -> ls.entry_point, Cil_types.Kglobal
+
 
   (* Conversion *)
 
   let to_legacy cs =
-    let l =
-      List.rev_map (fun (kf, stmt) -> (kf, Cil_types.Kstmt stmt)) cs.stack
-    in
-    List.rev ((cs.entry_point, Cil_types.Kglobal) :: l)
+    match cs with
+    | Global _vi -> []
+    | Local ls ->
+      let l =
+        List.rev_map (fun (kf, stmt) -> (kf, Cil_types.Kstmt stmt)) ls.stack
+      in
+      List.rev ((ls.entry_point, Cil_types.Kglobal) :: l)
 
   let to_kf_list cs =
-    cs.entry_point :: List.rev_map fst cs.stack
+    match cs with
+    | Global _vi -> []
+    | Local ls ->
+      ls.entry_point :: List.rev_map fst ls.stack
 
   let to_stmt_list cs =
-    List.rev_map snd cs.stack
+    match cs with
+    | Global _vi -> []
+    | Local ls ->
+      List.rev_map snd ls.stack
 end
diff --git a/src/kernel_services/abstract_interp/eva_types.mli b/src/kernel_services/abstract_interp/eva_types.mli
index 4862853563fe7431c4a11358f27216bb71c05d29..dc6b71c84df1d3dc9f8f7c0043e4f410ba58da89 100644
--- a/src/kernel_services/abstract_interp/eva_types.mli
+++ b/src/kernel_services/abstract_interp/eva_types.mli
@@ -29,21 +29,30 @@ sig
 
   module Call : Datatype.S with type t = call
 
-  type callstack = private {
+  type local_stack = private {
     thread: int;
     entry_point: Cil_types.kernel_function;
     stack: call list;
   }
 
+  type callstack = private
+    | Global of Cil_types.varinfo
+    | Local of local_stack
+
   include Datatype.S_with_collections with type t = callstack
 
-  val init : ?thread:int -> Cil_types.kernel_function -> t
+  val init_global : Cil_types.varinfo -> t
+  val init_local : ?thread:int -> Cil_types.kernel_function -> t
+
+  val is_local : t -> bool
+
   val push : Cil_types.kernel_function -> Cil_types.stmt -> t -> t
   val pop : t -> (Cil_types.kernel_function * Cil_types.stmt * t) option
   val top : t -> (Cil_types.kernel_function * Cil_types.stmt) option
   val top_kf : t -> Cil_types.kernel_function
   val top_callsite : t -> Cil_types.stmt option
   val top_call : t -> Cil_types.kernel_function * Cil_types.kinstr
+
   val to_legacy : t -> Value_types.callstack
   val to_kf_list : t -> Cil_types.kernel_function list
   val to_stmt_list : t -> Cil_types.stmt list
diff --git a/src/plugins/eva/Eva.mli b/src/plugins/eva/Eva.mli
index ae6966402a3d95bb0a717f9aa20f0327c0821201..18d459bb8869651e338068a2d54d008b7e7de21f 100644
--- a/src/plugins/eva/Eva.mli
+++ b/src/plugins/eva/Eva.mli
@@ -122,25 +122,33 @@ module Callstack: sig
 
   module Call : Datatype.S with type t = call
 
-  (** [callstack] is used to describe the analysis context when analysing a
+  (** [local_stack] is used to describe the analysis context when analysing a
       function. It contains the thread, the entry point and the list of
       calls from the entry point.
 
       This type is very likely to change in the future. Never use this type
       directly, prefer the use of the following functions when possible. *)
 
-  type callstack = Eva_types.Callstack.callstack = private {
+  type local_stack = Eva_types.Callstack.local_stack = private {
     thread: int; (* An identifier of the thread's callstack *)
     entry_point: Cil_types.kernel_function; (* The first function in the callstack *)
     stack: call list;
   }
 
+  type callstack = Eva_types.Callstack.callstack = private
+    | Global of Cil_types.varinfo
+    | Local of local_stack
+
   include Datatype.S_with_collections
     with type t = callstack
      and module Hashtbl = Eva_types.Callstack.Hashtbl
 
   (* Constructor *)
-  val init : ?thread:int -> Cil_types.kernel_function -> t
+  val init_global : Cil_types.varinfo -> t
+  val init_local : ?thread:int -> Cil_types.kernel_function -> t
+
+  (* Query *)
+  val is_local : t -> bool
 
   (* Stack manipulation *)
   val push : Cil_types.kernel_function -> Cil_types.stmt -> t -> t
diff --git a/src/plugins/eva/api/values_request.ml b/src/plugins/eva/api/values_request.ml
index a88453bcc12d9b2403a6850ae78c299a4c1dbe4e..468a733da7b5870bc81ba26668c03f7b03741a35 100644
--- a/src/plugins/eva/api/values_request.ml
+++ b/src/plugins/eva/api/values_request.ml
@@ -243,16 +243,19 @@ module Jcalls : Request.Output with type t = callstack = struct
     ]
 
   let to_json (cs : t) =
-    let aux (acc, jcaller) (callee, stmt) =
-      let jcallee = Jfct.to_json callee in
-      jcallsite jcaller jcallee stmt :: acc, jcallee
-    in
-    let entry_point = Jfct.to_json cs.entry_point in
-    let l, _last_callee = List.fold_left aux
-        ([`Assoc [ "callee", entry_point ]], entry_point)
-        cs.stack
-    in
-    `List (List.rev l)
+    match cs with
+    | Global _vi -> `List []
+    | Local ls ->
+      let aux (acc, jcaller) (callee, stmt) =
+        let jcallee = Jfct.to_json callee in
+        jcallsite jcaller jcallee stmt :: acc, jcallee
+      in
+      let entry_point = Jfct.to_json ls.entry_point in
+      let l, _last_callee = List.fold_left aux
+          ([`Assoc [ "callee", entry_point ]], entry_point)
+          ls.stack
+      in
+      `List (List.rev l)
 end
 
 module Jtruth : Data.S with type t = truth = struct
diff --git a/src/plugins/eva/engine/compute_functions.ml b/src/plugins/eva/engine/compute_functions.ml
index 9996485515fe99d557d6cc7a49a75f4578655d3a..4dd648dea88a98b7e190d431e52c3982f14873cf 100644
--- a/src/plugins/eva/engine/compute_functions.ml
+++ b/src/plugins/eva/engine/compute_functions.ml
@@ -352,14 +352,14 @@ module Make (Abstract: Abstractions.S_with_evaluation) = struct
   let compute kf init_state =
     let restore_signals = register_signal_handler () in
     let compute () =
-      let callstack = Callstack.init kf in
+      let callstack = Callstack.init_local kf in
       Eva_utils.set_call_stack callstack;
       store_initial_state callstack init_state;
       let call = { kf; callstack; arguments = []; rest = []; return = None; } in
       let final_result = compute_call Kglobal call None init_state in
       let final_states = List.map snd (final_result.Transfer.states) in
       let final_state = PowersetDomain.(final_states |> of_list |> join) in
-      Eva_utils.pop_call_stack ();
+      Eva_utils.clear_call_stack ();
       Self.feedback "done for function %a" Kernel_function.pretty kf;
       Abstract.Dom.Store.mark_as_computed ();
       Self.(set_computation_state Computed);
@@ -372,6 +372,7 @@ module Make (Abstract: Abstractions.S_with_evaluation) = struct
     let cleanup () =
       Abstract.Dom.Store.mark_as_computed ();
       Self.(set_computation_state Aborted);
+      Eva_utils.clear_call_stack ();
       post_analysis_cleanup ~aborted:true
     in
     Eva_utils.protect compute ~cleanup
diff --git a/src/plugins/eva/engine/initialization.ml b/src/plugins/eva/engine/initialization.ml
index ba5c5ea1c1539b2d72543981a0f827cab92722e1..c8850b93bee8a3c5dedc870fddc896544d2dba27 100644
--- a/src/plugins/eva/engine/initialization.ml
+++ b/src/plugins/eva/engine/initialization.ml
@@ -308,15 +308,21 @@ module Make
 
   let initialize_global_variable ~lib_entry vi init state =
     Cil.CurrentLoc.set vi.vdecl;
+    Eva_utils.set_call_stack (Callstack.init_global vi);
     let state = Domain.enter_scope Abstract_domain.Global [vi] state in
-    if vi.vsource then
-      let initialize =
-        if lib_entry || (vi.vstorage = Extern)
-        then initialize_var_lib_entry
-        else initialize_var_not_lib_entry ~local:false
-      in
-      initialize Kglobal vi init.init state
-    else state
+    let state = if vi.vsource then
+        let initialize =
+          if lib_entry || (vi.vstorage = Extern)
+          then initialize_var_lib_entry
+          else initialize_var_not_lib_entry ~local:false
+        in
+        initialize Kglobal vi init.init state
+      else state
+    in
+    Eva_utils.clear_call_stack ();
+    state
+
+
 
   (* Compute the initial state with all global variable initialized. *)
   let compute_global_state ~lib_entry () =
diff --git a/src/plugins/eva/types/callstack.mli b/src/plugins/eva/types/callstack.mli
index f794735b54fe1f6de26657ee333cedde9ae814a6..4a22d47031dc385f76e9856c0d396cd85b06df85 100644
--- a/src/plugins/eva/types/callstack.mli
+++ b/src/plugins/eva/types/callstack.mli
@@ -27,25 +27,33 @@ type call = Cil_types.kernel_function * Cil_types.stmt
 
 module Call : Datatype.S with type t = call
 
-(** [callstack] is used to describe the analysis context when analysing a
+(** [local_stack] is used to describe the analysis context when analysing a
     function. It contains the thread, the entry point and the list of
     calls from the entry point.
 
     This type is very likely to change in the future. Never use this type
     directly, prefer the use of the following functions when possible. *)
 
-type callstack = Eva_types.Callstack.callstack = private {
+type local_stack = Eva_types.Callstack.local_stack = private {
   thread: int; (* An identifier of the thread's callstack *)
   entry_point: Cil_types.kernel_function; (* The first function in the callstack *)
   stack: call list;
 }
 
+type callstack = Eva_types.Callstack.callstack = private
+  | Global of Cil_types.varinfo
+  | Local of local_stack
+
 include Datatype.S_with_collections
   with type t = callstack
    and module Hashtbl = Eva_types.Callstack.Hashtbl
 
 (* Constructor *)
-val init : ?thread:int -> Cil_types.kernel_function -> t
+val init_global : Cil_types.varinfo -> t
+val init_local : ?thread:int -> Cil_types.kernel_function -> t
+
+(* Query *)
+val is_local : t -> bool
 
 (* Stack manipulation *)
 val push : Cil_types.kernel_function -> Cil_types.stmt -> t -> t
diff --git a/src/plugins/eva/utils/eva_utils.ml b/src/plugins/eva/utils/eva_utils.ml
index 9ccd9540a5a2d237d11025419e29991aa8dc5196..0e9c181d9f04570c2abfa703284b6b30debcacba 100644
--- a/src/plugins/eva/utils/eva_utils.ml
+++ b/src/plugins/eva/utils/eva_utils.ml
@@ -27,12 +27,18 @@ open Cil_types
 let current_callstack : Callstack.t option ref = ref None
 
 let clear_call_stack () =
-  current_callstack := None
+  match !current_callstack with
+  | None -> ()
+  | Some cs ->
+    if Callstack.is_local cs then
+      Eva_perf.stop_doing (Callstack.to_legacy cs);
+    current_callstack := None
 
 let set_call_stack cs =
   assert (!current_callstack = None);
   current_callstack := Some cs;
-  Eva_perf.start_doing (Callstack.to_legacy cs)
+  if Callstack.is_local cs then
+    Eva_perf.start_doing (Callstack.to_legacy cs)
 
 let current_call_stack () =
   match !current_callstack with
diff --git a/src/plugins/eva/utils/results.ml b/src/plugins/eva/utils/results.ml
index 75728f5f0eb55e5ce139d6fe0f7dbaab16d70c35..897592d765ac58fb766445584e71a1afbec070a4 100644
--- a/src/plugins/eva/utils/results.ml
+++ b/src/plugins/eva/utils/results.ml
@@ -243,7 +243,7 @@ struct
       A.get_stmt_state_by_callstack ?selection ~after:true stmt
       |> by_callstack ctx
     | Initial ->
-      let cs = Callstack.init (fst (Globals.entry_point ())) in
+      let cs = Callstack.init_local (fst (Globals.entry_point ())) in
       A.get_global_state () |> singleton cs
     | Start kf ->
       A.get_initial_state_by_callstack ?selection kf |> by_callstack ctx