@@ -296,32 +296,32 @@ let locs = Hashtbl.create 200
296296
297297(* * Visitor to count locs appearing inside a fundec. *)
298298class countFnVisitor = object
299- inherit nopCilVisitor
300- method! vstmt s =
301- match s.skind with
302- | Return (_, loc)
303- | Goto (_, loc)
304- | ComputedGoto (_, loc)
305- | Break loc
306- | Continue loc
307- | If (_,_,_,loc,_)
308- | Switch (_,_,_,loc,_)
309- | Loop (_,loc,_,_,_)
310- -> Hashtbl. replace locs loc.line () ; DoChildren
311- | _ ->
312- DoChildren
313-
314- method! vinst = function
315- | Set (_,_,loc,_)
316- | Call (_,_,_,loc,_)
317- | Asm (_,_,_,_,_,loc)
318- -> Hashtbl. replace locs loc.line () ; SkipChildren
319- | _ -> SkipChildren
320-
321- method! vvdec _ = SkipChildren
322- method! vexpr _ = SkipChildren
323- method! vlval _ = SkipChildren
324- method! vtype _ = SkipChildren
299+ inherit nopCilVisitor
300+ method! vstmt s =
301+ match s.skind with
302+ | Return (_, loc)
303+ | Goto (_, loc)
304+ | ComputedGoto (_, loc)
305+ | Break loc
306+ | Continue loc
307+ | If (_,_,_,loc,_)
308+ | Switch (_,_,_,loc,_)
309+ | Loop (_,loc,_,_,_)
310+ -> Hashtbl. replace locs loc.line () ; DoChildren
311+ | _ ->
312+ DoChildren
313+
314+ method! vinst = function
315+ | Set (_,_,loc,_)
316+ | Call (_,_,_,loc,_)
317+ | Asm (_,_,_,_,_,loc)
318+ -> Hashtbl. replace locs loc.line () ; SkipChildren
319+ | _ -> SkipChildren
320+
321+ method! vvdec _ = SkipChildren
322+ method! vexpr _ = SkipChildren
323+ method! vlval _ = SkipChildren
324+ method! vtype _ = SkipChildren
325325end
326326
327327let fnvis = new countFnVisitor
@@ -346,16 +346,16 @@ module StmtH = Hashtbl.Make (CilType.Stmt)
346346
347347let stmt_fundecs: fundec StmtH. t ResettableLazy. t =
348348 ResettableLazy. from_fun (fun () ->
349- let h = StmtH. create 113 in
350- iterGlobals ! current_file (function
351- | GFun (fd , _ ) ->
352- List. iter (fun stmt ->
353- StmtH. replace h stmt fd
354- ) fd.sallstmts
355- | _ -> ()
356- );
357- h
358- )
349+ let h = StmtH. create 113 in
350+ iterGlobals ! current_file (function
351+ | GFun (fd , _ ) ->
352+ List. iter (fun stmt ->
353+ StmtH. replace h stmt fd
354+ ) fd.sallstmts
355+ | _ -> ()
356+ );
357+ h
358+ )
359359
360360let pseudo_return_to_fun = StmtH. create 113
361361
@@ -369,14 +369,14 @@ module VarinfoH = Hashtbl.Make (CilType.Varinfo)
369369
370370let varinfo_fundecs: fundec VarinfoH. t ResettableLazy. t =
371371 ResettableLazy. from_fun (fun () ->
372- let h = VarinfoH. create 111 in
373- iterGlobals ! current_file (function
374- | GFun (fd , _ ) ->
375- VarinfoH. replace h fd.svar fd
376- | _ -> ()
377- );
378- h
379- )
372+ let h = VarinfoH. create 111 in
373+ iterGlobals ! current_file (function
374+ | GFun (fd , _ ) ->
375+ VarinfoH. replace h fd.svar fd
376+ | _ -> ()
377+ );
378+ h
379+ )
380380
381381(* * Find [fundec] by the function's [varinfo] (has the function name and type). *)
382382let find_varinfo_fundec vi = VarinfoH. find (ResettableLazy. force varinfo_fundecs) vi (* vi argument must be explicit, otherwise force happens immediately *)
@@ -386,14 +386,14 @@ module StringH = Hashtbl.Make (Printable.Strings)
386386
387387let name_fundecs: fundec StringH. t ResettableLazy. t =
388388 ResettableLazy. from_fun (fun () ->
389- let h = StringH. create 111 in
390- iterGlobals ! current_file (function
391- | GFun (fd , _ ) ->
392- StringH. replace h fd.svar.vname fd
393- | _ -> ()
394- );
395- h
396- )
389+ let h = StringH. create 111 in
390+ iterGlobals ! current_file (function
391+ | GFun (fd , _ ) ->
392+ StringH. replace h fd.svar.vname fd
393+ | _ -> ()
394+ );
395+ h
396+ )
397397
398398(* * Find [fundec] by the function's name. *)
399399(* TODO: why unused? *)
@@ -408,19 +408,19 @@ type varinfo_role =
408408
409409let varinfo_roles: varinfo_role VarinfoH. t ResettableLazy. t =
410410 ResettableLazy. from_fun (fun () ->
411- let h = VarinfoH. create 113 in
412- iterGlobals ! current_file (function
413- | GFun (fd , _ ) ->
414- VarinfoH. replace h fd.svar Function ; (* function itself can be used as a variable (function pointer) *)
415- List. iter (fun vi -> VarinfoH. replace h vi (Formal fd)) fd.sformals;
416- List. iter (fun vi -> VarinfoH. replace h vi (Local fd)) fd.slocals
417- | GVar (vi, _, _)
418- | GVarDecl (vi , _ ) ->
419- VarinfoH. replace h vi Global
420- | _ -> ()
421- );
422- h
423- )
411+ let h = VarinfoH. create 113 in
412+ iterGlobals ! current_file (function
413+ | GFun (fd , _ ) ->
414+ VarinfoH. replace h fd.svar Function ; (* function itself can be used as a variable (function pointer) *)
415+ List. iter (fun vi -> VarinfoH. replace h vi (Formal fd)) fd.sformals;
416+ List. iter (fun vi -> VarinfoH. replace h vi (Local fd)) fd.slocals
417+ | GVar (vi, _, _)
418+ | GVarDecl (vi , _ ) ->
419+ VarinfoH. replace h vi Global
420+ | _ -> ()
421+ );
422+ h
423+ )
424424
425425(* * Find the role of the [varinfo]. *)
426426let find_varinfo_role vi = VarinfoH. find (ResettableLazy. force varinfo_roles) vi (* vi argument must be explicit, otherwise force happens immediately *)
@@ -449,15 +449,15 @@ let find_scope_fundec vi =
449449let original_names: string VarinfoH. t ResettableLazy. t =
450450 (* only invert environment map when necessary (e.g. witnesses) *)
451451 ResettableLazy. from_fun (fun () ->
452- let h = VarinfoH. create 113 in
453- Hashtbl. iter (fun original_name (envdata , _ ) ->
454- match envdata with
455- | Cabs2cil. EnvVar vi when vi.vname <> " " -> (* TODO: fix temporary variables with empty names being in here *)
456- VarinfoH. replace h vi original_name
457- | _ -> ()
458- ) Cabs2cil. environment;
459- h
460- )
452+ let h = VarinfoH. create 113 in
453+ Hashtbl. iter (fun original_name (envdata , _ ) ->
454+ match envdata with
455+ | Cabs2cil. EnvVar vi when vi.vname <> " " -> (* TODO: fix temporary variables with empty names being in here *)
456+ VarinfoH. replace h vi original_name
457+ | _ -> ()
458+ ) Cabs2cil. environment;
459+ h
460+ )
461461
462462(* * Find the original name (in input source code) of the [varinfo].
463463 If it was renamed by CIL, then returns the original name before renaming.
@@ -480,3 +480,21 @@ let stmt_pretty_short () x =
480480 | Instr (y ::ys ) -> dn_instr () y
481481 | If (exp ,_ ,_ ,_ ,_ ) -> dn_exp () exp
482482 | _ -> dn_stmt () x
483+
484+ (* * Given a [Cil.file], reorders its [globals], inserts function declarations before function definitions.
485+ This function may be used after a code transformation to ensure that the order of globals yields a compilable program. *)
486+ let add_function_declarations (file : Cil.file ): unit =
487+ let globals = file.globals in
488+ let functions, non_functions = List. partition (fun g -> match g with GFun _ -> true | _ -> false ) globals in
489+ let upto_last_type, non_types = GobList. until_last_with (fun g -> match g with GType _ -> true | _ -> false ) non_functions in
490+ let declaration_from_GFun f = match f with
491+ | GFun (f , _ ) when String. starts_with ~prefix: " __builtin" f.svar.vname ->
492+ (* Builtin functions should not occur in asserts generated, so there is no need to add declarations for them.*)
493+ None
494+ | GFun (f , _ ) ->
495+ Some (GVarDecl (f.svar, locUnknown))
496+ | _ -> failwith " Expected GFun, but was something else."
497+ in
498+ let fun_decls = List. filter_map declaration_from_GFun functions in
499+ let globals = upto_last_type @ fun_decls @ non_types @ functions in
500+ file.globals < - globals
0 commit comments