@@ -1637,7 +1637,7 @@ struct
16371637 let find_fps e xs = Addr. to_var_must e @ xs in
16381638 let vars = AD. fold find_fps adrs [] in
16391639 let funs = List. filter (fun x -> isFunctionType x.vtype) vars in
1640- List. iter (fun x -> ctx.spawn x [] ) funs
1640+ List. iter (fun x -> ctx.spawn None x [] ) funs
16411641 | _ -> ()
16421642 );
16431643 match lval with (* this section ensure global variables contain bottom values of the proper type before setting them *)
@@ -1748,7 +1748,13 @@ struct
17481748 | TFun (ret , _ , _ , _ ) -> ret
17491749 | _ -> assert false
17501750 in
1751- set ~t_override ctx.ask ctx.global nst (return_var () ) t_override (eval_rv ctx.ask ctx.global ctx.local exp)
1751+ let rv = eval_rv ctx.ask ctx.global ctx.local exp in
1752+ let nst =
1753+ match ThreadId. get_current ctx.ask with
1754+ | `Lifted tid when ThreadReturn. is_current ctx.ask -> Tuple2. map1 (CPA. add tid rv) nst
1755+ | _ -> nst
1756+ in
1757+ set ~t_override ctx.ask ctx.global nst (return_var () ) t_override rv
17521758 (* lval_raw:None, and rval_raw:None is correct here *)
17531759
17541760 let vdecl ctx (v :varinfo ) =
@@ -1834,8 +1840,8 @@ struct
18341840
18351841
18361842
1837- let forkfun (ctx :(D.t, G.t, C.t) Analyses.ctx ) (lv : lval option ) (f : varinfo ) (args : exp list ) : (varinfo * exp list) list =
1838- let create_thread arg v =
1843+ let forkfun (ctx :(D.t, G.t, C.t) Analyses.ctx ) (lv : lval option ) (f : varinfo ) (args : exp list ) : (lval option * varinfo * exp list) list =
1844+ let create_thread lval arg v =
18391845 try
18401846 (* try to get function declaration *)
18411847 let fd = Cilfacade. getdec v in
@@ -1844,25 +1850,25 @@ struct
18441850 | Some x -> [x]
18451851 | None -> List. map (fun x -> MyCFG. unknown_exp) fd.sformals
18461852 in
1847- Some (v, args)
1853+ Some (lval, v, args)
18481854 with Not_found ->
18491855 if LF. use_special f.vname then None (* we handle this function *)
18501856 else if isFunctionType v.vtype then (
18511857 M. warn_each (" Creating a thread from unknown function " ^ v.vname);
1852- Some (v, args)
1858+ Some (lval, v, args)
18531859 ) else (
18541860 M. warn_each (" Not creating a thread from " ^ v.vname ^ " because its type is " ^ sprint d_type v.vtype);
18551861 None
18561862 )
18571863 in
18581864 match LF. classify f.vname args with
18591865 (* handling thread creations *)
1860- | `ThreadCreate (start ,ptc_arg ) -> begin
1866+ | `ThreadCreate (id , start ,ptc_arg ) -> begin
18611867 (* extra sync so that we do not analyze new threads with bottom global invariant *)
18621868 publish_all ctx;
18631869 (* Collect the threads. *)
18641870 let start_addr = eval_tv ctx.ask ctx.global ctx.local start in
1865- List. filter_map (create_thread (Some ptc_arg)) (AD. to_var_may start_addr)
1871+ List. filter_map (create_thread (Some ( Mem id, NoOffset )) ( Some ptc_arg)) (AD. to_var_may start_addr)
18661872 end
18671873 | `Unknown _ when get_bool " exp.unknown_funs_spawn" -> begin
18681874 let args =
@@ -1872,7 +1878,7 @@ struct
18721878 in
18731879 let flist = collect_funargs ctx.ask ctx.global ctx.local args in
18741880 let addrs = List. concat (List. map AD. to_var_may flist) in
1875- List. filter_map (create_thread None ) addrs
1881+ List. filter_map (create_thread None None ) addrs
18761882 end
18771883 | _ -> []
18781884
@@ -1928,8 +1934,8 @@ struct
19281934 let special ctx (lv :lval option ) (f : varinfo ) (args : exp list ) =
19291935 (* let heap_var = heap_var !Tracing.current_loc in*)
19301936 let forks = forkfun ctx lv f args in
1931- if M. tracing then if not (List. is_empty forks) then M. tracel " spawn" " Base.special %s: spawning functions %a\n " f.vname (d_list " ," d_varinfo) (List. map fst forks);
1932- List. iter (uncurry ctx.spawn) forks;
1937+ if M. tracing then if not (List. is_empty forks) then M. tracel " spawn" " Base.special %s: spawning functions %a\n " f.vname (d_list " ," d_varinfo) (List. map BatTuple.Tuple3. second forks);
1938+ List. iter (BatTuple.Tuple3. uncurry ctx.spawn) forks;
19331939 let cpa,dep as st = ctx.local in
19341940 let gs = ctx.global in
19351941 match LF. classify f.vname args with
@@ -2012,7 +2018,18 @@ struct
20122018 end
20132019 | `Unknown "exit" -> raise Deadcode
20142020 | `Unknown "abort" -> raise Deadcode
2015- | `Unknown "pthread_exit" -> raise Deadcode (* TODO: somehow actually return value, pthread_join doesn't handle anyway? *)
2021+ | `Unknown "pthread_exit" ->
2022+ begin match args with
2023+ | [exp] ->
2024+ begin match ThreadId. get_current ctx.ask with
2025+ | `Lifted tid ->
2026+ let rv = eval_rv ctx.ask ctx.global ctx.local exp in
2027+ ctx.sideg tid rv
2028+ | _ -> ()
2029+ end ;
2030+ raise Deadcode
2031+ | _ -> failwith " Unknown pthread_exit."
2032+ end
20162033 | `Unknown "__builtin_expect" ->
20172034 begin match lv with
20182035 | Some v -> assign ctx v (List. hd args)
@@ -2023,10 +2040,20 @@ struct
20232040 | Some x -> assign ctx x (List. hd args)
20242041 | None -> ctx.local
20252042 end
2043+ (* handling thread creations *)
2044+ | `ThreadCreate _ ->
2045+ D. bot () (* actual results joined via threadspawn *)
20262046 (* handling thread joins... sort of *)
20272047 | `ThreadJoin (id ,ret_var ) ->
20282048 begin match (eval_rv ctx.ask gs st ret_var) with
20292049 | `Int n when GU. opt_predicate (BI. equal BI. zero) (ID. to_int n) -> cpa,dep
2050+ | `Address ret_a ->
2051+ begin match eval_rv ctx.ask gs st id with
2052+ | `Address a ->
2053+ (* TODO: is this type right? *)
2054+ set ctx.ask gs st ret_a (Cil. typeOf ret_var) (get ctx.ask gs st a None )
2055+ | _ -> invalidate ctx.ask gs st [ret_var]
2056+ end
20302057 | _ -> invalidate ctx.ask gs st [ret_var]
20312058 end
20322059 | `Malloc size -> begin
@@ -2145,15 +2172,25 @@ struct
21452172 Printable. get_short_list (GU. demangle f.svar.vname ^ " (" ) " )" 80 args_short
21462173
21472174
2148- let threadenter ctx (f : varinfo ) (args : exp list ): D.t =
2175+ let threadenter ctx (lval : lval option ) ( f : varinfo ) (args : exp list ): D.t =
21492176 try
21502177 make_entry ctx f args
21512178 with Not_found ->
21522179 (* Unknown functions *)
21532180 ctx.local
21542181
2155- let threadspawn ctx (f : varinfo ) (args : exp list ) fctx : D.t =
2156- D. bot ()
2182+ let threadspawn ctx (lval : lval option ) (f : varinfo ) (args : exp list ) fctx : D.t =
2183+ match lval with
2184+ | Some lval ->
2185+ begin match ThreadId. get_current fctx.ask with
2186+ | `Lifted tid ->
2187+ (* TODO: is this type right? *)
2188+ set ctx.ask ctx.global ctx.local (eval_lv ctx.ask ctx.global ctx.local lval) (Cil. typeOfLval lval) (`Address (AD. from_var tid))
2189+ | _ ->
2190+ ctx.local
2191+ end
2192+ | None ->
2193+ ctx.local
21572194end
21582195
21592196module type MainSpec = sig
0 commit comments