Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
frama-c
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
frama-c
Commits
384f5304
Commit
384f5304
authored
5 years ago
by
Basile Desloges
Browse files
Options
Downloads
Patches
Plain Diff
[eacsl:codegen] Create and call globals delete function at the end of main
parent
7fe8fce0
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/plugins/e-acsl/src/code_generator/injector.ml
+103
-19
103 additions, 19 deletions
src/plugins/e-acsl/src/code_generator/injector.ml
with
103 additions
and
19 deletions
src/plugins/e-acsl/src/code_generator/injector.ml
+
103
−
19
View file @
384f5304
...
...
@@ -329,6 +329,40 @@ let add_new_block_in_stmt env kf stmt =
"@[new stmt (from sid %d):@ %a@]"
stmt
.
sid
Printer
.
pp_stmt
new_stmt
;
new_stmt
,
env
(** In the block [outer_block] in the function [kf], this function finds the
innermost last statement and insert the list of statements returned by
[last_stmts].
The function [last_stmts] receives an optional argument [?return_stmt] with
the innermost return statement if it exists. In that case the function needs
to return this statement as the last statement. *)
let
insert_as_last_stmts_in_innermost_block
~
last_stmts
kf
outer_block
=
(* Retrieve the last innermost block *)
let
rec
retrieve_innermost_last_return
block
=
let
l
=
List
.
rev
block
.
bstmts
in
match
l
with
|
[]
->
block
,
[]
,
None
|
{
skind
=
Return
_
}
as
ret
::
rest
->
block
,
rest
,
Some
ret
|
{
skind
=
Block
b
}
::
_
->
retrieve_innermost_last_return
b
|
_
::
_
->
block
,
l
,
None
in
let
inner_block
,
rev_content
,
return_stmt
=
retrieve_innermost_last_return
outer_block
in
(* Create the statements to insert *)
let
new_stmts
=
last_stmts
?
return_stmt
()
in
(* Move the labels from the return stmt to the stmts to insert *)
let
new_stmts
=
match
return_stmt
with
|
Some
return_stmt
->
let
b
=
Cil
.
mkBlock
new_stmts
in
let
new_stmt
=
Constructor
.
mk_block
return_stmt
b
in
E_acsl_label
.
move
kf
return_stmt
new_stmt
;
[
new_stmt
]
|
None
->
new_stmts
in
(* Insert the statements as the last statements of the innermost block *)
inner_block
.
bstmts
<-
List
.
rev_append
rev_content
new_stmts
(* visit the substmts and build the new skind *)
let
rec
inject_in_substmt
env
kf
stmt
=
match
stmt
.
skind
with
|
Instr
instr
->
...
...
@@ -670,27 +704,59 @@ let inject_in_global (env, main) = function
->
env
,
main
(* Insert [stmt_begin] as the first statement of [fundec] and insert [stmt_end] as
the last before [return] *)
let
surround_function_with
kf
fundec
stmt_begin
stmt_end
=
let
body
=
fundec
.
sbody
in
(* Insert last statement *)
Extlib
.
may
(
fun
stmt_end
->
let
last_stmts
?
return_stmt
()
=
match
return_stmt
with
|
Some
return_stmt
->
[
stmt_end
;
return_stmt
]
|
None
->
[
stmt_end
]
in
insert_as_last_stmts_in_innermost_block
~
last_stmts
kf
body
)
stmt_end
;
(* Insert first statement *)
body
.
bstmts
<-
stmt_begin
::
body
.
bstmts
(* TODO: what about using [file.globalinit]? *)
let
inject_global_initializer
file
main
=
Options
.
feedback
~
dkey
~
level
:
2
"building global initializer."
;
let
vi
,
fundec
=
Global_observer
.
mk_init_function
()
in
let
cil_fct
=
GFun
(
fundec
,
Location
.
unknown
)
in
if
Mmodel_analysis
.
use_model
()
then
begin
if
Mmodel_analysis
.
use_model
()
then
(* Create [__e_acsl_globals_init] function *)
let
vi_init
,
fundec_init
=
Global_observer
.
mk_init_function
()
in
let
cil_fct_init
=
GFun
(
fundec_init
,
Location
.
unknown
)
in
(* Create [__e_acsl_globals_delete] function *)
let
vi_delete
,
fundec_delete
=
Global_observer
.
mk_delete_function
()
in
let
cil_fct_delete
=
GFun
(
fundec_delete
,
Location
.
unknown
)
in
match
main
with
|
Some
main
->
let
exp
=
Cil
.
evar
~
loc
:
Location
.
unknown
vi
in
(* Create [__e_acsl_globals_init();] call *)
let
stmt
=
Cil
.
mkStmtOneInstr
~
valid_sid
:
true
(
Call
(
None
,
exp
,
[]
,
Location
.
unknown
))
let
mk_fct_call
vi
=
let
exp
=
Cil
.
evar
~
loc
:
Location
.
unknown
vi
in
let
stmt
=
Cil
.
mkStmtOneInstr
~
valid_sid
:
true
(
Call
(
None
,
exp
,
[]
,
Location
.
unknown
))
in
vi
.
vreferenced
<-
true
;
stmt
in
vi
.
vreferenced
<-
true
;
(* insert [__e_acsl_globals_init ();] as first statement of [main] *)
let
main_fundec
=
try
Kernel_function
.
get_definition
main
let
main_fundec
=
try
Kernel_function
.
get_definition
main
with
_
->
assert
false
(* by construction, the main kf has a fundec *)
in
main_fundec
.
sbody
.
bstmts
<-
stmt
::
main_fundec
.
sbody
.
bstmts
;
(* Create [__e_acsl_globals_init();] call *)
let
stmt_init
=
mk_fct_call
vi_init
in
(* Create [__e_acsl_globals_delete();] call *)
let
stmt_delete
=
match
fundec_delete
.
sbody
.
bstmts
with
|
[]
->
None
|
_
->
Some
(
mk_fct_call
vi_delete
)
in
(* Surround the content of main with the calls to
[__e_acsl_globals_init();] and [__e_acsl_globals_delete();] *)
surround_function_with
main
main_fundec
stmt_init
stmt_delete
;
(* Retrieve all globals except main *)
let
main_vi
=
Globals
.
Functions
.
get_vi
main
in
let
new_globals
=
...
...
@@ -701,13 +767,24 @@ let inject_global_initializer file main =
[]
file
.
globals
in
(* Add the globals functions and re-add main at the end *)
let
new_globals
=
let
rec
rev_and_extend
acc
=
function
|
[]
->
acc
|
f
::
l
->
rev_and_extend
(
f
::
acc
)
l
in
(* [__e_acsl_globals_init] and [main] at the end *)
rev_and_extend
[
cil_fct
;
GFun
(
main_fundec
,
Location
.
unknown
)
]
new_globals
(* [main] at the end *)
let
globals_to_add
=
[
GFun
(
main_fundec
,
Location
.
unknown
)
]
in
(* Prepend [__e_acsl_globals_delete] if not empty *)
let
globals_to_add
=
match
fundec_delete
.
sbody
.
bstmts
with
|
[]
->
globals_to_add
|
_
->
cil_fct_delete
::
globals_to_add
in
(* Prepend [__e_acsl_globals_init] *)
let
globals_to_add
=
cil_fct_init
::
globals_to_add
in
(* Add these functions to the globals *)
rev_and_extend
globals_to_add
new_globals
in
(* add the literal string varinfos as the very first globals *)
let
new_globals
=
...
...
@@ -718,10 +795,17 @@ let inject_global_initializer file main =
file
.
globals
<-
new_globals
|
None
->
Kernel
.
warning
"@[no entry point specified:@ \
you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
Global_observer
.
function_init_name
;
file
.
globals
<-
file
.
globals
@
[
cil_fct
]
end
you must call functions `%s', `%s', \
`__e_acsl_memory_init' and `__e_acsl_memory_clean' \
by yourself.@]"
Global_observer
.
function_init_name
Global_observer
.
function_delete_name
;
let
globals_func
=
match
fundec_delete
.
sbody
.
bstmts
with
|
[]
->
[
cil_fct_init
]
|
_
->
[
cil_fct_init
;
cil_fct_delete
]
in
file
.
globals
<-
file
.
globals
@
globals_func
(* Add a call to [__e_acsl_memory_init] that initializes memory storage and
potentially records program arguments. Parameters to [__e_acsl_memory_init]
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment