aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Schmidt <github@mschmidt.me>2023-01-16 15:35:11 +0100
committerXavier Leroy <xavier.leroy@college-de-france.fr>2023-01-23 18:14:20 +0100
commit3ebc2e9bd947aa213f2bc5eaf19fe9ffc8f9b5ca (patch)
tree688882626c0b35d9bc20e5a965ebf4121971cfba
parent800017c36c15774bdcc7dc5b318fa9606caa4170 (diff)
downloadcompcert-3ebc2e9bd947aa213f2bc5eaf19fe9ffc8f9b5ca.tar.gz
compcert-3ebc2e9bd947aa213f2bc5eaf19fe9ffc8f9b5ca.zip
Disable tail calls in variadic functions
Variadic functions can use the stack frame to store values of registers. Hence, a pointer within the stack frame can be put in a va_list, and the stack frame should not be deallocated before a function call that may use this va_list. Fixes: #473
-rw-r--r--backend/Tailcall.v1
-rw-r--r--backend/Tailcallproof.v10
2 files changed, 6 insertions, 5 deletions
diff --git a/backend/Tailcall.v b/backend/Tailcall.v
index b7a62d74..2da07ee8 100644
--- a/backend/Tailcall.v
+++ b/backend/Tailcall.v
@@ -93,6 +93,7 @@ Definition transf_instr (f: function) (pc: node) (instr: instruction) :=
Definition transf_function (f: function) : function :=
if zeq f.(fn_stacksize) 0
+ && option_eq zeq f.(fn_sig).(sig_cc).(cc_vararg) None
then RTL.transf_function (transf_instr f) f
else f.
diff --git a/backend/Tailcallproof.v b/backend/Tailcallproof.v
index 7a5be5ed..c109e1b6 100644
--- a/backend/Tailcallproof.v
+++ b/backend/Tailcallproof.v
@@ -169,7 +169,8 @@ Lemma transf_instr_lookup:
exists i', (transf_function f).(fn_code)!pc = Some i' /\ transf_instr_spec f i i'.
Proof.
intros. unfold transf_function.
- destruct (zeq (fn_stacksize f) 0).
+ destruct (zeq (fn_stacksize f) 0 && option_eq zeq (cc_vararg (sig_cc (fn_sig f))) None) eqn:B.
+ InvBooleans.
simpl. rewrite PTree.gmap. rewrite H. simpl.
exists (transf_instr f pc i); split. auto. apply transf_instr_charact; auto.
exists i; split. auto. constructor.
@@ -240,14 +241,14 @@ Lemma sig_preserved:
forall f, funsig (transf_fundef f) = funsig f.
Proof.
destruct f; auto. simpl. unfold transf_function.
- destruct (zeq (fn_stacksize f) 0); auto.
+ destruct (zeq (fn_stacksize f) 0 && option_eq zeq (cc_vararg (sig_cc (fn_sig f))) None); auto.
Qed.
Lemma stacksize_preserved:
forall f, fn_stacksize (transf_function f) = fn_stacksize f.
Proof.
unfold transf_function. intros.
- destruct (zeq (fn_stacksize f) 0); auto.
+ destruct (zeq (fn_stacksize f) 0 && option_eq zeq (cc_vararg (sig_cc (fn_sig f))) None); auto.
Qed.
Lemma find_function_translated:
@@ -534,7 +535,7 @@ Proof.
assert (fn_stacksize (transf_function f) = fn_stacksize f /\
fn_entrypoint (transf_function f) = fn_entrypoint f /\
fn_params (transf_function f) = fn_params f).
- unfold transf_function. destruct (zeq (fn_stacksize f) 0); auto.
+ unfold transf_function. destruct (zeq (fn_stacksize f) 0 && option_eq zeq (cc_vararg (sig_cc (fn_sig f))) None); auto.
destruct H0 as [EQ1 [EQ2 EQ3]].
left. econstructor; split.
simpl. eapply exec_function_internal; eauto. rewrite EQ1; eauto.
@@ -602,4 +603,3 @@ Proof.
Qed.
End PRESERVATION.
-