@@ -415,7 +415,71 @@ let init () =
415415 if not (Sys. file_exists path) then (
416416 Logs. error " witness.yaml.validate: %s not found" path;
417417 Svcomp. errorwith " witness missing"
418- )
418+ );
419+ let file = ! Cilfacade. current_file in
420+ let global_vars =
421+ file.globals
422+ |> List. filter_map (function
423+ | Cil. GVar (v, _, _)
424+ | Cil. GVarDecl (v, _)
425+ | Cil. GFun ({svar = v ; _} , _ ) -> Some (v.vname, Cil. Fv v)
426+ | _ -> None
427+ )
428+ in
429+ let has_global name =
430+ List. exists (function
431+ | Cil. GVar (v, _, _)
432+ | Cil. GVarDecl (v, _)
433+ | Cil. GFun ({svar = v ; _} , _ ) -> String. equal v.vname name
434+ | _ -> false
435+ ) file.globals
436+ in
437+ let parse_type (type_ : string ): Cil.typ option =
438+ try Some (Formatcil. cType type_ [] ) with
439+ | exn when GobExn. catch_all_filter exn ->
440+ M. warn_noloc ~category: Witness " ghost variable type parse failed: %s" type_;
441+ None
442+ in
443+ let parse_init (init : string ): Cil.exp option =
444+ try Some (Formatcil. cExp init global_vars) with
445+ | exn when GobExn. catch_all_filter exn ->
446+ M. warn_noloc ~category: Witness " ghost variable initializer parse failed: %s" init;
447+ None
448+ in
449+ let instrument_ghost_variable (variable : YamlWitnessType.GhostInstrumentation.Variable.t ): unit =
450+ if not (String. equal variable.scope " global" ) then (
451+ M. warn_noloc ~category: Witness " unsupported ghost variable scope: %s" variable.scope
452+ )
453+ else if has_global variable.name then (
454+ M. error_noloc ~category: Witness " ghost variable already declared in program: %s" variable.name;
455+ Svcomp. errorwith " witness error"
456+ )
457+ else
458+ match parse_type variable.type_, parse_init variable.initial.value with
459+ | Some typ , Some init ->
460+ let v = makeGlobalVar variable.name typ in
461+ let g = GVar (v, {init = Some (SingleInit init)}, locUnknown) in
462+ file.globals < - g :: file.globals
463+ | _ ->
464+ M. error_noloc ~category: Witness " failed to instrument ghost variable declaration: %s" variable.name
465+ in
466+ let instrument_ghost_variables yaml_entry =
467+ match YamlWitnessType.Entry. of_yaml yaml_entry with
468+ | Ok {entry_type = YamlWitnessType.EntryType. GhostInstrumentation {ghost_variables; _} ; _} ->
469+ List. iter instrument_ghost_variable ghost_variables
470+ | Ok _ ->
471+ ()
472+ | Error (`Msg m ) ->
473+ M. error_noloc ~category: Witness " couldn't parse entry while extracting ghost instrumentation: %s" m
474+ in
475+ let yaml = match GobResult.Syntax. (Fpath. of_string path >> = Yaml_unix. of_file) with
476+ | Ok yaml -> yaml
477+ | Error (`Msg m ) ->
478+ Logs. error " Yaml_unix.of_file: %s" m;
479+ Svcomp. errorwith " witness missing"
480+ in
481+ let yaml_entries = yaml |> GobYaml. list |> BatResult. get_ok in
482+ List. iter instrument_ghost_variables yaml_entries
419483
420484let loc_of_location (location : YamlWitnessType.Location.t ): Cil.location = {
421485 file = location.file_name;
0 commit comments