source: Papers/fopara2013/fopara13.tex @ 3431

Last change on this file since 3431 was 3431, checked in by campbell, 6 years ago

Note the specification language in Sec 3.

File size: 64.0 KB
Line 
1\documentclass{llncs}
2
3\usepackage{amsfonts}
4\usepackage{amsmath}
5\usepackage{amssymb} 
6\usepackage[english]{babel}
7\usepackage{color}
8\usepackage{fancybox}
9\usepackage{fancyvrb}
10\usepackage{graphicx}
11\usepackage[colorlinks,
12            bookmarks,bookmarksopen,bookmarksdepth=2]{hyperref}
13\usepackage{hyphenat}
14\usepackage[utf8x]{inputenc}
15\usepackage{listings}
16\usepackage{mdwlist}
17\usepackage{microtype}
18\usepackage{stmaryrd}
19\usepackage{url}
20
21\usepackage{tikz}
22\usetikzlibrary{positioning,calc,patterns,chains,shapes.geometric,scopes}
23
24%\renewcommand{\verb}{\lstinline}
25%\def\lstlanguagefiles{lst-grafite.tex}
26%\lstset{language=Grafite}
27\lstset{language=C,basicstyle=\tt,basewidth=.5em,lineskip=-1.5pt}
28
29\newlength{\mylength}
30\newenvironment{frametxt}%
31        {\setlength{\fboxsep}{5pt}
32                \setlength{\mylength}{\linewidth}%
33                \addtolength{\mylength}{-2\fboxsep}%
34                \addtolength{\mylength}{-2\fboxrule}%
35                \Sbox
36                \minipage{\mylength}%
37                        \setlength{\abovedisplayskip}{0pt}%
38                        \setlength{\belowdisplayskip}{0pt}%
39                }%
40                {\endminipage\endSbox
41                        \[\fbox{\TheSbox}\]}
42
43\title{Certified Complexity (CerCo)\thanks{The project CerCo acknowledges the
44financial support of the Future and Emerging Technologies (FET) programme within
45the Seventh Framework Programme for Research of the European Commission, under
46FET-Open grant number: 243881}}
47\author{
48%Roberto
49R.~M. Amadio$^{4}$ \and
50%Nicolas
51N.~Ayache$^{3,4}$ \and
52%François
53F.~Bobot$^{3,4}$ \and
54%Jacob
55J.~P. Boender$^1$ \and
56%Brian
57B.~Campbell$^2$ \and
58%Ilias
59I.~Garnier$^2$ \and
60%Antoine
61A.~Madet$^4$ \and
62%James
63J.~McKinna$^2$ \and
64%Dominic
65D.~P. Mulligan$^1$ \and
66%Mauro
67M.~Piccolo$^1$ \and
68%Randy
69R.~Pollack$^2$ \and
70%Yann
71Y.~R\'egis-Gianas$^{3,4}$ \and
72%Claudio
73C.~Sacerdoti Coen$^1$ \and
74%Ian
75I.~Stark$^2$ \and
76%Paolo
77P.~Tranquilli$^1$}
78\institute{Dipartimento di Informatica - Scienza e Ingegneria, Universit\'a di
79Bologna \and
80LFCS, School of Informatics, University of Edinburgh
81\and INRIA (Team $\pi r^2$)
82\and
83Universit\`e Paris Diderot
84}
85
86\bibliographystyle{splncs03}
87
88\begin{document}
89
90\maketitle
91
92% Brian: I've changed "without loss of accuracy" because we discuss
93% important precision/complexity tradeoffs for advanced architectures
94% in the dependent labelling section.
95\begin{abstract}
96This paper provides an overview of the FET-Open Project CerCo
97(`Certified Complexity'). The project's main achievement is
98the development of a technique for analysing non-functional
99properties of programs (time, space) at the source level, with little or no loss of accuracy
100and with a small trusted code base. The main software component
101developed is a certified compiler producing cost annotations. The compiler
102translates source code to object code and produces an instrumented copy of the
103source code. This instrumentation exposes at
104the source level---and tracks precisely---the actual (non-asymptotic)
105computational cost of the input program. Untrusted invariant generators and trusted theorem provers
106can then be used to compute and certify the parametric execution time of the
107code.
108\end{abstract}
109
110% ---------------------------------------------------------------------------- %
111% SECTION                                                                      %
112% ---------------------------------------------------------------------------- %
113\section{Introduction}
114
115%\paragraph{Problem statement.}
116Computer programs can be specified with both
117functional constraints (what a program must do) and non-functional constraints
118(what resources---time, space, etc.---the program may use).  In the current
119state of the art, functional properties are verified for high-level source code
120by combining user annotations (e.g. preconditions and invariants) with a
121multitude of automated analyses (invariant generators, type systems, abstract
122interpretation, theorem proving, and so on). By contrast, non-functional properties
123are generally checked on low-level object code, but also demand information
124about high-level functional behaviour that must somehow be reconstructed.
125
126This situation presents several problems: 1) it can be hard to infer this
127high-level structure in the presence of compiler optimisations; 2) techniques
128working on object code are not useful in early development, yet problems
129detected later are more expensive to tackle; 3) parametric cost analysis is very
130hard: how can we reflect a cost that depends on the execution state (e.g. the
131value of a register or a carry bit) to a cost that the user can understand
132looking at source code? 4) performing functional analysis on the object code
133makes it hard for the programmer to provide information, leading to less precision in
134the estimates.
135
136\paragraph{Vision and approach.} We want to reconcile functional and
137non-functional analyses: to share information and perform both at the same time
138on source code.
139%
140What has previously prevented this approach is the lack of a uniform and precise
141cost model for high-level code: 1) each statement occurrence is compiled
142differently and optimisations may change control flow; 2) the cost of an object
143code instruction may depend on the runtime state of hardware components like
144pipelines and caches, all of which are not visible in the source code.
145
146To solve the issue, we envision a new generation of compilers able to keep track
147of program structure through compilation and optimisation, and to exploit that
148information to define a cost model for source code that is precise, non-uniform,
149and which accounts for runtime state. With such a source-level cost model we can
150reduce non-functional verification to the functional case and exploit the state
151of the art in automated high-level verification~\cite{survey}. The techniques
152currently used by the Worst Case Execution Time (WCET) community, which perform the analysis on object code,
153are still available but can now be coupled with an additional source-level
154analysis. Where the approach produces precise cost models too complex to reason
155about, safe approximations can be used to trade complexity with precision.
156Finally, source code analysis can be used during the early stages of development, when
157components have been specified but not implemented: source code modularity means
158that it is enough to specify the non-functional behaviour of unimplemented
159components.
160
161\paragraph{Contributions.} We have developed what we refer to as \emph{the labeling approach} \cite{labeling}, a
162technique to implement compilers that induce cost models on source programs by
163very lightweight tracking of code changes through compilation. We have studied
164how to formally prove the correctness of compilers implementing this technique.
165We have implemented such a compiler from C to object binaries for the 8051
166micro-controller, and verified it in an interactive theorem prover.
167
168To demonstrate source-level verification of costs we have implemented
169a Frama-C plugin \cite{framac} that invokes the compiler on a source
170program and uses this to generate invariants on the high-level source
171that correctly model low-level costs. The plugin certifies that the
172program respects these costs by calling automated theorem provers, a
173new and innovative technique in the field of cost analysis. Finally,
174we have conduct several case studies, including showing that the
175plugin can automatically compute and certify the exact reaction time
176of Lustre~\cite{lustre} data flow programs compiled into C.
177
178\section{Project context and approach}
179Formal methods for verification of functional properties of programs have
180now reached a level of maturity and automation that is facilitating a slow but
181increasing adoption in production environments. For safety critical code, it is
182becoming commonplace to combine rigorous software engineering methodologies and testing
183with static analysis, taking the strong points of each approach and mitigating
184their weaknesses. Of particular interest are open frameworks
185for the combination of different formal methods, where the programs can be
186progressively specified and are continuously enriched with new safety
187guarantees: every method contributes knowledge (e.g. new invariants) that
188becomes an assumption for later analysis.
189
190The scenario for the verification of non-functional properties (time spent,
191memory used, energy consumed) is bleaker.
192% and the future seems to be getting even worse.
193Most industries verify that real time systems meet their deadlines
194by simply performing many runs of the system and timing their execution,  computing the
195maximum time and adding an empirical safety margin, claiming the result to be a
196bound for the WCET of the program. Formal methods and software to statically
197analyse the WCET of programs exist, but they often produce bounds that are too
198pessimistic to be useful. Recent advancements in hardware architecture
199have been
200focused on the improvement of the average case performance, not the
201predictability of the worst case. Execution time is becoming increasingly
202dependent on execution history and the internal state of
203hardware components like pipelines and caches. Multi-core processors and non-uniform
204memory models are drastically reducing the possibility of performing
205static analysis in isolation, because programs are less and less time
206composable. Clock-precise hardware models are necessary for static analysis, and
207obtaining them is becoming harder due to the increased sophistication
208of hardware design.
209
210Despite the aforementioned problems, the need for reliable real time
211systems and programs is increasing, and there is increasing pressure
212from the research community towards the introduction of alternative
213hardware with more predictable behaviour, which would be more suitable
214for static analysis.  One example being investigated by the Proartis
215project~\cite{proartis} is to decouple execution time from execution
216history by introducing randomisation.
217
218In the CerCo project \cite{cerco} we do not try to address this problem, optimistically
219assuming that improvements in low-level timing analysis or architecture will make
220verification feasible in the longer term. The main objective of our work is
221instead to bring together static analysis of functional and non-functional
222properties, which, according to the current state of the art, are completely
223independent activities with limited exchange of information: while the
224functional properties are verified on the source code, the analysis of
225non-functional properties is entirely performed on the object code to exploit
226clock-precise hardware models.
227
228\subsection{Current object-code methods}
229
230Analysis currently takes place on object code for two main reasons.
231First, there cannot be a uniform, precise cost model for source
232code instructions (or even basic blocks). During compilation, high level
233instructions are torn apart and reassembled in context-specific ways so that
234identifying a fragment of object code and a single high level instruction is
235infeasible. Even the control flow of the object and source code can be very
236different as a result of optimisations, for example aggressive loop
237optimisations may completely transform source level loops. Despite the lack of a uniform, compilation- and
238program-independent cost model on the source language, the literature on the
239analysis of non-asymptotic execution time on high level languages that assumes
240such a model is growing and gaining momentum. However, unless we provide a
241replacement for such cost models, this literature's future practical impact looks
242to be minimal. Some hope has been provided by the EmBounded project \cite{embounded}, which
243compositionally compiles high-level code to a byte code that is executed by an
244interpreter with guarantees on the maximal execution time spent for each byte code
245instruction. This provides a uniform model at the expense of the model's
246precision (each cost is a pessimistic upper bound) and the performance of the
247executed code (because the byte code is interpreted compositionally instead of
248performing a fully non-compositional compilation).
249
250The second reason to perform the analysis on the object code is that bounding
251the worst case execution time of small code fragments in isolation (e.g. loop
252bodies) and then adding up the bounds yields very poor estimates because no
253knowledge of the hardware state on executing the fragment can be assumed. By
254analysing longer runs the bound obtained becomes more precise because the lack
255of information about the initial state has a relatively small impact.
256
257To calculate the cost of an execution, value and control flow analyses
258are required to bound the number of times each basic block is
259executed.  Current state
260of the art WCET technology such as AbsInt performs these analyses on the
261object code, where the logic of the program is harder to reconstruct
262and most information available at the source code level has been lost;
263see~\cite{stateart} for a survey. Imprecision in the analysis can lead to useless bounds. To
264augment precision, the tools ask the user to provide constraints on
265the object code control flow, usually in the form of bounds on the
266number of iterations of loops or linear inequalities on them. This
267requires the user to manually link the source and object code,
268translating his assumptions on the source code (which may be wrong) to
269object code constraints. The task is error prone and hard, especially
270in the presence of complex compiler optimisations.
271
272Traditional techniques for WCET that work on object code are also affected by
273another problem: they cannot be applied before the generation of the object
274code. Functional properties can be analysed in early development stages, while
275analysis of non-functional properties may come too late to avoid expensive
276changes to the program architecture.
277
278\subsection{CerCo}
279
280In CerCo we propose a radically new approach to the problem: we reject the idea
281of a uniform cost model and we propose that the compiler, which knows how the
282code is translated, must return the cost model for basic blocks of high level
283instructions. It must do so by keeping track of the control flow modifications
284to reverse them and by interfacing with processor timing analysis.
285
286By embracing compilation, instead of avoiding it like EmBounded did, a CerCo
287compiler can both produce efficient code and return costs that are
288as precise as the processor timing analysis can be. Moreover, our costs can be
289parametric: the cost of a block can depend on actual program data, on a
290summary of the execution history, or on an approximated representation of the
291hardware state. For example, loop optimizations may assign to a loop body a cost
292that is a function of the number of iterations performed. As another example,
293the cost of a block may be a function of the vector of stalled pipeline states,
294which can be exposed in the source code and updated at each basic block exit. It
295is parametricity that allows one to analyse small code fragments without losing
296precision: in the analysis of the code fragment we do not have to ignore the
297initial hardware state. On the contrary, we can assume that we know exactly which
298state (or mode, as the WCET literature calls it) we are in.
299
300The CerCo approach has the potential to dramatically improve the state of the
301art. By performing control and data flow analyses on the source code, the error
302prone translation of invariants is completely avoided. It is in fact performed
303by the compiler itself when it induces the cost model on the source language.
304Moreover, any available technique for the verification of functional properties
305can be immediately reused and multiple techniques can collaborate together to
306infer and certify cost invariants for the program. Parametric cost analysis
307becomes the default one, with non-parametric bounds used as a last resort when
308trading the complexity of the analysis with its precision. \emph{A priori}, no
309technique previously used in traditional WCET is lost: processor
310timing analyses can be used by the compiler on the object code, and the rest can be applied
311at the source code level.
312 Our approach can also work in the early
313stages of development by axiomatically attaching costs to unimplemented components.
314
315
316All software used to verify properties of programs must be as bug free as
317possible. The trusted code base for verification consists of the code that needs
318to be trusted to believe that the property holds. The trusted code base of
319state-of-the-art WCET tools is very large: one needs to trust the control flow
320analyser and the linear programming libraries it uses and also the formal models
321of the hardware. In CerCo we are moving the control flow analysis to the source
322code and we are introducing a non-standard compiler too. To reduce the trusted
323code base, we implemented a prototype and a static analyser in an interactive
324theorem prover, which was used to certify that the costs added to the source
325code are indeed those incurred by the hardware. Formal models of the
326hardware and of the high level source languages were also implemented in the
327interactive theorem prover. Control flow analysis on the source code has been
328obtained using invariant generators, tools to produce proof obligations from
329generated invariants and automatic theorem provers to verify the obligations. If
330the automatic provers are able to generate proof traces that can be
331independently checked, the only remaining component that enters the trusted code
332base is an off-the-shelf invariant generator which, in turn, can be proved
333correct using an interactive theorem prover. Therefore we achieve the double
334objective of allowing the use of more off-the-shelf components (e.g. provers and
335invariant generators) whilst reducing the trusted code base at the same time.
336
337%\paragraph{Summary of the CerCo objectives.} To summarize, the goal of CerCo is
338% to reconcile functional with non-functional analysis by performing them together
339% on the source code, sharing common knowledge about execution invariants. We want
340% to achieve the goal implementing a new generation of compilers that induce a
341% parametric, precise cost model for basic blocks on the source code. The compiler
342% should be certified using an interactive theorem prover to minimize the trusted
343% code base of the analysis. Once the cost model is induced, off-the-shelf tools
344% and techniques can be combined together to infer and prove parametric cost
345% bounds.
346%The long term benefits of the CerCo vision are expected to be:
347%1. the possibility to perform static analysis during early development stages
348%2.  parametric bounds made easier
349%3.  the application of off-the-shelf techniques currently unused for the
350% analysis of non-functional properties, like automated proving and type systems
351%4. simpler and safer interaction with the user, that is still asked for
352% knowledge, but on the source code, with the additional possibility of actually
353% verifying the provided knowledge
354%5. a reduced trusted code base
355%6. the increased accuracy of the bounds themselves.
356%
357%The long term success of the project is hindered by the increased complexity of
358% the static prediction of the non-functional behaviour of modern hardware. In the
359% time frame of the European contribution we have focused on the general
360% methodology and on the difficulties related to the development and certification
361% of a cost model inducing compiler.
362
363\section{The typical CerCo workflow}
364\begin{figure}[!t]
365\begin{tabular}{l@{\hspace{0.2cm}}|@{\hspace{0.2cm}}l}
366\begin{lstlisting}
367char a[] = {3, 2, 7, 14};
368char threshold = 4;
369
370int count(char *p, int len) {
371  char j;
372  int found = 0;
373  for (j=0; j < len; j++) {
374    if (*p <= threshold)
375      found++;
376    p++;
377    }
378  return found;
379}
380
381int main() {
382  return count(a,4);
383}
384\end{lstlisting}
385&
386%  $\vcenter{\includegraphics[width=7.5cm]{interaction_diagram.pdf}}$
387\begin{tikzpicture}[
388    baseline={([yshift=-.5ex]current bounding box)},
389    element/.style={draw, text width=1.6cm, on chain, text badly centered},
390    >=stealth
391    ]
392{[start chain=going below, node distance=.5cm]
393\node [element] (cerco) {CerCo\\compiler};
394\node [element] (cost)  {CerCo\\cost plugin};
395{[densely dashed]
396\node [element] (ded)   {Deductive\\platform};
397\node [element] (check) {Proof\\checker};
398}
399}
400\coordinate [left=3.5cm of cerco] (left);
401{[every node/.style={above, text width=3.5cm, text badly centered,
402                     font=\scriptsize}]
403\draw [<-] ([yshift=-1ex]cerco.north west) coordinate (t) --
404    node {C source}
405    (t-|left);
406\draw [->] (cerco) -- (cost);
407\draw [->] ([yshift=1ex]cerco.south west) coordinate (t) --
408    node {C source+\color{red}{cost annotations}}
409    (t-|left) coordinate (cerco out);
410\draw [->] ([yshift=1ex]cost.south west) coordinate (t) --
411    node {C source+\color{red}{cost annotations}\\+\color{blue}{synthesized assertions}}
412    (t-|left) coordinate (out);
413{[densely dashed]
414\draw [<-] ([yshift=-1ex]ded.north west) coordinate (t) --
415    node {C source+\color{red}{cost annotations}\\+\color{blue}{complexity assertions}}
416    (t-|left) coordinate (ded in) .. controls +(-.5, 0) and +(-.5, 0) .. (out);
417\draw [->] ([yshift=1ex]ded.south west) coordinate (t) --
418    node {complexity obligations}
419    (t-|left) coordinate (out);
420\draw [<-] ([yshift=-1ex]check.north west) coordinate (t) --
421    node {complexity proof}
422    (t-|left) .. controls +(-.5, 0) and +(-.5, 0) .. (out);
423\draw [dash phase=2.5pt] (cerco out) .. controls +(-1, 0) and +(-1, 0) ..
424    (ded in);
425}}
426%% user:
427% head
428\draw (current bounding box.west) ++(-.2,.5)
429    circle (.2) ++(0,-.2) -- ++(0,-.1) coordinate (t);
430% arms
431\draw (t) -- +(-.3,-.2);
432\draw (t) -- +(.3,-.2);
433% body
434\draw (t) -- ++(0,-.4) coordinate (t);
435% legs
436\draw (t) -- +(-.2,-.6);
437\draw (t) -- +(.2,-.6);
438\end{tikzpicture}
439\end{tabular}
440\caption{On the left: code to count the array's elements
441 that are less than or equal to the threshold. On the right: CerCo's interaction
442 diagram. CerCo's components are drawn solid.}
443\label{test1}
444\end{figure}
445We illustrate the workflow we envisage (on the right
446of~\autoref{test1}) on an example program (on the left
447of~\autoref{test1}).  The user writes the program and feeds it to the
448CerCo compiler, which outputs an instrumented version of the same
449program that updates global variables that record the elapsed
450execution time and the stack space usage.  The red lines in
451\autoref{itest1} introducing variables, functions and function calls
452starting with \lstinline'__cost' and \lstinline'__stack' are the instrumentation introduced by the
453compiler.  For example, the two calls at the start of
454\lstinline'count' say that 4 bytes of stack are required, and that it
455takes 111 cycles to reach the next cost annotation (in the loop body).
456The compiler measures these on the labeled object code that it generates.
457
458 The annotated program can then be enriched with complexity
459assertions in the style of Hoare logic, that are passed to a deductive
460platform (in our case Frama-C). We provide as a Frama-C cost plugin a
461simple automatic synthesiser for complexity assertions which can
462be overridden by the user to increase or decrease accuracy.  These are the blue
463comments starting with \lstinline'/*@' in \autoref{itest1}, written in
464Frama-C's specification language, ACSL.  From the
465assertions, a general purpose deductive platform produces proof
466obligations which in turn can be closed by automatic or interactive
467provers, ending in a proof certificate.
468
469% NB: if you try this example with the live CD you should increase the timeout
470
471Twelve proof obligations are generated from~\autoref{itest1} (to prove
472that the loop invariant holds after one execution if it holds before,
473to prove that the whole program execution takes at most 1358 cycles,
474etc.).  Note that the synthesised time bound for \lstinline'count',
475$178+214*(1+\text{\lstinline'len'})$ cycles, is parametric in the length of
476the array. The CVC3 prover
477closes all obligations within half a minute on routine commodity
478hardware.  A simpler non-parametric version can be solved in a few
479seconds.
480%
481\fvset{commandchars=\\\{\}}
482\lstset{morecomment=[s][\color{blue}]{/*@}{*/},
483        moredelim=[is][\color{blue}]{$}{$},
484        moredelim=[is][\color{red}]{|}{|},
485        lineskip=-2pt}
486\begin{figure}[!p]
487\begin{lstlisting}
488|int __cost = 33, __stack = 5, __stack_max = 5;|
489|void __cost_incr(int incr) { __cost += incr; }|
490|void __stack_incr(int incr) {
491  __stack += incr;
492  __stack_max = __stack_max < __stack ? __stack : __stack_max;
493}|
494
495char a[4] = {3, 2, 7, 14};  char threshold = 4;
496
497/*@ behavior stack_cost:
498      ensures __stack_max <= __max(\old(__stack_max), 4+\old(__stack));
499      ensures __stack == \old(__stack);
500    behavior time_cost:
501      ensures __cost <= \old(__cost)+(178+214*__max(1+\at(len,Pre), 0));
502*/
503int count(char *p, int len) {
504  char j;  int found = 0;
505  |__stack_incr(4);  __cost_incr(111);|
506  $__l: /* internal */$
507  /*@ for time_cost: loop invariant
508        __cost <= \at(__cost,__l)+
509                  214*(__max(\at((len-j)+1,__l), 0)-__max(1+(len-j), 0));
510      for stack_cost: loop invariant
511        __stack_max == \at(__stack_max,__l);
512      for stack_cost: loop invariant
513        __stack == \at(__stack,__l);
514      loop variant len-j;
515  */
516  for (j = 0; j < len; j++) {
517    |__cost_incr(78);|
518    if (*p <= threshold) { |__cost_incr(136);| found ++; }
519    else { |__cost_incr(114);| }
520    p ++;
521  }
522  |__cost_incr(67);  __stack_incr(-4);|
523  return found;
524}
525
526/*@ behavior stack_cost:
527      ensures __stack_max <= __max(\old(__stack_max), 6+\old(__stack));
528      ensures __stack == \old(__stack);
529    behavior time_cost:
530      ensures __cost <= \old(__cost)+1358;
531*/
532int main(void) {
533  int t;
534  |__stack_incr(2);  __cost_incr(110);|
535  t = count(a,4);
536  |__stack_incr(-2);|
537  return t;
538}
539\end{lstlisting}
540\caption{The instrumented version of the program in \autoref{test1},
541 with instrumentation added by the CerCo compiler in red and cost invariants
542 added by the CerCo Frama-C plugin in blue. The \texttt{\_\_cost},
543 \texttt{\_\_stack} and \texttt{\_\_stack\_max} variables hold the elapsed time
544in clock cycles and the current and maximum stack usage. Their initial values
545hold the clock cycles spent in initialising the global data before calling
546\texttt{main} and the space required by global data (and thus unavailable for
547the stack).
548}
549\label{itest1}
550\end{figure}
551\section{Main scientific and technical results}
552First we describe the basic labeling approach and our compiler
553implementations that use it.  This is suitable for basic architectures
554with simple cost models.  Then we will discuss the dependent labeling
555extension which is suitable for more advanced processor architectures
556and compiler optimisations.  At the end of this section we will
557demonstrate automated high level reasoning about the source level
558costs provided by the compilers.
559
560% \emph{Dependent labeling~\cite{?}.} The basic labeling approach assumes a
561% bijective mapping between object code and source code O(1) blocks (called basic
562% blocks). This assumption is violated by many program optimizations (e.g. loop
563% peeling and loop unrolling). It also assumes the cost model computed on the
564% object code to be non parametric: every block must be assigned a cost that does
565% not depend on the state. This assumption is violated by stateful hardware like
566% pipelines, caches, branch prediction units. The dependent labeling approach is
567% an extension of the basic labeling approach that allows to handle parametric
568% cost models. We showed how the method allows to deal with loop optimizations and
569% pipelines, and we speculated about its applications to caches.
570%
571% \emph{Techniques to exploit the induced cost model.} Every technique used for
572% the analysis of functional properties of programs can be adapted to analyse the
573% non-functional properties of the source code instrumented by compilers that
574% implement the labeling approach. In order to gain confidence in this claim, we
575% showed how to implement a cost invariant generator combining abstract
576% interpretation with separation logic ideas \cite{separation}. We integrated
577% everything in the Frama-C modular architecture, in order to compute proof
578% obligations from functional and cost invariants and to use automatic theorem
579% provers on them. This is an example of a new technique that is not currently
580% exploited in WCET analysis. It also shows how precise functional invariants
581% benefits the non-functional analysis too. Finally, we show how to fully
582% automatically analyse the reaction time of Lustre nodes that are first compiled
583% to C using a standard Lustre compiler and then processed by a C compiler that
584% implements the labeling approach.
585
586% \emph{The CerCo compiler.} This is a compiler from a large subset of the C
587% program to 8051/8052 object code,
588% integrating the labeling approach and a static analyser for 8051 executables.
589% The latter can be implemented easily and does not require dependent costs
590% because the 8051 microprocessor is a very simple one, with constant-cost
591% instruction. It was chosen to separate the issue of exact propagation of the
592% cost model from the orthogonal problem of the static analysis of object code
593% that may require approximations or dependent costs. The compiler comes in
594% several versions: some are prototypes implemented directly in OCaml, and they
595% implement both the basic and dependent labeling approaches; the final version
596% is extracted from a Matita certification and at the moment implements only the
597% basic approach.
598
599\subsection{The (basic) labeling approach}
600The labeling approach is the foundational insight that underlies all the developments in CerCo.
601It allows the tracking of the evolution of
602basic blocks during the compilation process in order to propagate the cost model from the
603object code to the source code without losing precision in the process.
604\paragraph{Problem statement.} Given a source program $P$, we want to obtain an
605instrumented source program $P'$,  written in the same programming language, and
606the object code $O$ such that: 1) $P'$ is obtained by inserting into $P$ some
607additional instructions to update global cost information like the amount of
608time spent during execution or the maximal stack space required; 2) $P$ and $P'$ 
609must have the same functional behaviour, i.e.\ they must produce that same output
610and intermediate observables; 3) $P$ and $O$ must have the same functional
611behaviour; 4) after execution and in interesting points during execution, the
612cost information computed by $P'$ must be an upper bound of the one spent by $O$ 
613to perform the corresponding operations (soundness property); 5) the difference
614between the costs computed by $P'$ and the execution costs of $O$ must be
615bounded by a program-dependent constant (precision property).
616
617\paragraph{The labeling software components.} We solve the problem in four
618stages \cite{labeling}, implemented by four software components that are used
619in sequence.
620
621The first component labels the source program $P$ by injecting label emission
622statements in appropriate positions to mark the beginning of basic blocks.
623% The
624% set of labels with their positions is called labeling.
625The syntax and semantics
626of the source programming language is augmented with label emission statements.
627The statement ``EMIT $\ell$'' behaves like a NOP instruction that does not affect the
628program state or control flow, but its execution is observable.
629% Therefore the observables of a run of a program becomes a stream
630% of label emissions: $\ell_1,\ldots,\ell_n$, called the program trace. We clarify the conditions
631% that the labeling must respect later.
632
633The second component is a labeling preserving compiler. It can be obtained from
634an existing compiler by adding label emission statements to every intermediate
635language and by propagating label emission statements during compilation. The
636compiler is correct if it preserves both the functional behaviour of the program
637and the traces of observables.
638% We may also ask that the function that erases the cost
639% emission statements commute with compilation. This optional property grants that
640% the labeling does not interfere with the original compiler behaviour. A further
641% set of requirements will be added later.
642
643The third component is a static object code analyser. It takes as input a labeled
644object code and it computes the scope of each of its label emission statements,
645i.e.\ the tree of instructions that may be executed after the statement and before
646a new label emission is encountered.
647It is a tree and not a sequence because the scope
648may contain a branching statement. In order to grant that such a finite tree
649exists, the object code must not contain any loop that is not broken by a label
650emission statement. This is the first requirement of a sound labeling. The
651analyser fails if the labeling is unsound. For each scope, the analyser
652computes an upper bound of the execution time required by the scope, using the
653maximum of the costs of the two branches in case of a conditional statement.
654Finally, the analyser computes the cost of a label by taking the maximum of the
655costs of the scopes of every statement that emits that label.
656
657The fourth and last component takes in input the cost model computed at step 3
658and the labelled code computed at step 1. It outputs a source program obtained
659by replacing each label emission statement with a statement that increments the
660global cost variable with the cost associated to the label by the cost model. 
661The obtained source code is the instrumented source code.
662
663\paragraph{Correctness.} Requirements 1, 2 and 3 of the problem statement
664obviously hold, with 2 and 3 being a consequence of the definition of a correct
665labeling preserving compiler. It is also obvious that the value of the global
666cost variable of an instrumented source code is at any time equal to the sum of
667the costs of the labels emitted by the corresponding labelled code. Moreover,
668because the compiler preserves all traces, the sum of the costs of the labels
669emitted in the source and target labelled code are the same. Therefore, to
670satisfy the fourth requirement, we need to grant that the time taken to execute
671the object code is equal to the sum of the costs of the labels emitted by the
672object code. We collect all the necessary conditions for this to happen in the
673definition of a sound labeling: a) all loops must be broken by a cost emission
674statement;  b) all program instructions must be in the scope of some cost
675emission statement. To satisfy also the fifth requirement, additional
676requirements must be imposed on the object code labeling to avoid all uses of
677the maximum in the cost computation: the labeling is precise if every label is
678emitted at most once and both branches of a conditional jump start with a label
679emission statement.
680
681The correctness and precision of the labeling approach only rely on the
682correctness and precision of the object code labeling. The simplest
683way to achieve them is to impose correctness and precision
684requirements also on the initial labeling produced by the first software
685component, and to ask the compiler to preserve these
686properties too. The latter requirement imposes serious limitations on the
687compilation strategy and optimizations: the compiler may not duplicate any code
688that contains label emission statements, like loop bodies. Therefore several
689loop optimisations like peeling or unrolling are prevented. Moreover, precision
690of the object code labeling is not sufficient \emph{per se} to obtain global
691precision: we implicitly assumed that a precise constant cost can be assigned
692to every instruction. This is not possible in
693the presence of stateful hardware whose state influences the cost of operations,
694like pipelines and caches. In Section~\ref{lab:deplabel} we will see an extension of the
695basic labeling approach to cover this situation.
696
697In CerCo we have developed several cost preserving compilers based on
698the labeling approach. Excluding an initial certified compiler for a
699`while' language, all remaining compilers target realistic source
700languages---a pure higher order functional language and a large subset
701of C with pointers, gotos and all data structures---and real world
702target processors---MIPS and the Intel 8051/8052 processor
703family. Moreover, they achieve a level of optimisation that ranges
704from moderate (comparable to GCC level 1) to intermediate (including
705loop peeling and unrolling, hoisting and late constant propagation).
706We describe the C compilers in detail in the following section.
707
708Two compilation chains were implemented for a purely functional
709higher-order language~\cite{labeling2}. The two main changes required
710to deal with functional languages are: 1) because global variables and
711updates are not available, the instrumentation phase produces monadic
712code to `update' the global costs; 2) the requirements for a sound and
713precise labeling of the source code must be changed when the
714compilation is based on CPS translations.  In particular, we need to
715introduce labels emitted before a statement is executed and also
716labels emitted after a statement is executed. The latter capture code
717that is inserted by the CPS translation and that would escape all
718label scopes.
719
720% Brian: one of the reviewers pointed out that standard Prolog implementations
721% do have some global state that apparently survives backtracking and might be
722% used.  As we haven't experimented with this, I think it's best to elide it
723% entirely.
724
725% Phases 1, 2 and 3 can be applied as well to logic languages (e.g. Prolog).
726% However, the instrumentation phase cannot: in standard Prolog there is no notion
727% of (global) variable whose state is not retracted during backtracking.
728% Therefore, the cost of executing computations that are later backtracked would
729% not be correctly counted in. Any extension of logic languages with
730% non-backtrackable state could support our labeling approach.
731
732\subsection{The CerCo C compilers}
733We implemented two C compilers, one implemented directly in OCaml and
734the other implemented in the interactive theorem prover
735Matita~\cite{matita}.  The first acted as a prototype for the second,
736but also supported MIPS and acted as a testbed for more advanced
737features such as the dependent labeling approach
738in Section~\ref{lab:deplabel}.
739
740The second C compiler is the \emph{Trusted CerCo Compiler}, whose cost
741predictions are formally verified. The code distributed
742is extracted OCaml code from the Matita implementation. In the rest of
743this section we will only focus on the Trusted CerCo Compiler, that only targets
744the C language and the 8051/8052 family, and that does not implement any
745advanced optimisations yet. Its user interface, however, is the same as the one
746of the other version, in order to trade safety with additional performances. In
747particular, the Frama-C CerCo plugin can work without recompilation
748with both of our C compilers.
749
750The 8051/8052 microprocessor is a very simple one, with constant-cost
751instructions. It was chosen to separate the issue of exact propagation of the
752cost model from the orthogonal problem of the static analysis of object code
753that may require approximations or dependent costs.
754
755The (trusted) CerCo compiler implements the following optimisations: cast
756simplification, constant propagation in expressions, liveness analysis driven
757spilling of registers, dead code elimination, branch displacement, and tunneling.
758The two latter optimisations are performed by our optimising assembler
759\cite{correctness}. The back-end of the compiler works on three address
760instructions, preferred to static single assignment code for the simplicity of
761the formal certification.
762
763The CerCo compiler is loosely based on the CompCert compiler \cite{compcert}, a
764recently developed certified compiler from C to the PowerPC, ARM and x86
765microprocessors. In contrast to CompCert, both the CerCo code and its
766certification are fully open source. Some data structures and language definitions for
767the front-end are directly taken from CompCert, while the back-end is a redesign
768of a compiler from Pascal to MIPS used by Fran\c{c}ois Pottier for a course at the
769Ecole Polytechnique.
770
771The main differences in the CerCo compiler are:
772\begin{enumerate}
773\item All the intermediate languages include label emitting instructions to
774implement the labeling approach, and the compiler preserves execution traces.
775\item Traditionally compilers target an assembly language with additional
776macro-instructions to be expanded before assembly; for CerCo we need to go all
777the way down to object code in order to perform the static analysis. Therefore
778we integrated also an optimising assembler and a static analyser.
779\item In order to avoid the additional work of implementing a linker
780 and a loader, we do not support separate
781compilation and external calls. Adding them is orthogonal
782to the labeling approach and should not introduce extra problems.
783\item We target an 8-bit processor, in contrast to CompCert's 32-bit targets. This requires
784many changes and more compiler code, but it is not fundamentally more
785complex. The proof of correctness, however, becomes much harder.
786\item We target a microprocessor that has a non-uniform memory model, which is
787still often the case for microprocessors used in embedded systems and that is
788becoming common again in multi-core processors. Therefore the compiler has to
789keep track of data and it must move data between memory regions in the proper
790way. Moreover the size of pointers to different regions is not uniform. An
791additional difficulty was that the space available for the stack in internal
792memory in the 8051 is tiny, allowing only a minor number of nested calls. To
793support full recursion in order to test the CerCo tools also on recursive
794programs, the compiler implements a stack in external memory.
795\end{enumerate}
796
797\subsection{Formal certification of the CerCo compiler}
798We have formally
799certified in the Matita interactive proof assistant that the cost models induced on the source code by the
800Trusted CerCo Compiler correctly and precisely
801predict the object code behaviour. There are two cost models, one for execution
802time and one for stack space consumption. We show the correctness of the prediction
803only for those programs that do not exhaust the available machine stack space, a
804property that---thanks to the stack cost model---we can statically analyse on the
805source code using our Frama-C tool. The preservation of functional properties we
806take as an assumption, not itself formally proved in CerCo.  Other projects have
807already certified the preservation of functional semantics in similar compilers,
808and we have not attempted to directly repeat that work. In order to complete the
809proof for non-functional properties, we have introduced a new semantics for
810programming languages based on a new kind of structured observables with the
811relative notions of forward similarity and the study of the intensional
812consequences of forward similarity. We have also introduced a unified
813representation for back-end intermediate languages that was exploited to provide
814a uniform proof of forward similarity.
815
816The details on the proof techniques employed
817and
818the proof sketch can be collected from the CerCo deliverables and papers.
819In this section we will only hint at the correctness statement, which turned
820out to be more complex than what we expected at the beginning.
821
822\paragraph{The statement.}
823Real time programs are often reactive programs that loop forever responding to
824events (inputs) by performing some computation followed by some action (output)
825and the return to the initial state. For looping programs the overall execution
826time does not make sense. The same happens for reactive programs that spend an
827unpredictable amount of time in I/O. What is interesting is the reaction time
828that measure the time spent between I/O events. Moreover, we are interested in
829predicting and ruling out crashes due to running out of space on certain
830inputs.
831Therefore we need to look for a statement that talks about sub-runs of a
832program. The most natural statement is that the time predicted on the source
833code and spent on the object code by two corresponding sub-runs are the same.
834The problem to solve to make this statement formal is how to identify the
835corresponding sub-runs and how to single out those that are meaningful.
836The solution we found is based on the notion of measurability. We say that a run
837has a \emph{measurable sub-run} when both the prefix of the sub-run and the
838sub-run do not exhaust the stack space, the number of function calls and returns
839in the sub-run is the same, the sub-run does not perform any I/O and the sub-run
840starts with a label emission statement and ends with a return or another label
841emission statements. The stack usage is estimated using the stack usage model
842that is computed by the compiler.
843
844The statement that we formally proved is: for each C run with a measurable
845sub-run, there exists an object code run with a sub-run, such that the observables
846of the pairs of prefixes and sub-runs are the same and the time spent by the
847object code in the sub-run is the same as the one predicted on the source code
848using the time cost model generated by the compiler.
849We briefly discuss the constraints for measurability. Not exhausting the stack
850space is a clear requirement of meaningfulness of a run, because source programs
851do not crash for lack of space while object code ones do. The balancing of
852function calls and returns is a requirement for precision: the labeling approach
853allows the scope of label emission statements to extend after function calls to
854minimize the number of labels. Therefore a label pays for all the instructions
855in a block, excluding those executed in nested function calls. If the number of
856calls/returns is unbalanced, it means that there is a call we have not returned
857to that could be followed by additional instructions whose cost has already been
858taken in account. To make the statement true (but less precise) in this
859situation, we could only say that the cost predicted on the source code is a
860safe bound, not that it is exact. The last condition on the entry/exit points of
861a run is used to identify sub-runs whose code correspond to a sequence of blocks
862that we can measure precisely. Any other choice would start or end the run in the
863middle of a block and we would be forced again to weaken the statement taking as
864a bound the cost obtained counting in all the instructions that precede the
865starting one in the block, or follow the final one in the block.
866I/O operations can be performed in the prefix of the run, but not in the
867measurable sub-run. Therefore we prove that we can predict reaction times, but
868not I/O times, as desired.
869
870\subsection{Dependent labeling}
871\label{lab:deplabel}
872The core idea of the basic labeling approach is to establish a tight connection
873between basic blocks executed in the source and target languages. Once the
874connection is established, any cost model computed on the object code can be
875transferred to the source code, without affecting the code of the compiler or
876its proof. In particular, it is immediate that we can also transport cost models
877that associate to each label functions from hardware state to natural numbers.
878However, a problem arises during the instrumentation phase that replaces cost
879emission statements with increments of global cost variables. The global cost
880variable must be incremented with the result of applying the function associated
881to the label to the hardware state at the time of execution of the block.
882The hardware state comprises both the functional state that affects the
883computation (the value of the registers and memory) and the non-functional
884state that does not (the pipeline and cache contents, for example). The former is
885in correspondence with the source code state, but reconstructing the
886correspondence may be hard and lifting the cost model to work on the source code
887state is likely to produce cost expressions that are too complex to understand and reason about.
888Fortunately, in all modern architectures the cost of executing single
889instructions is either independent of the functional state or the jitter---the
890difference between the worst and best case execution times---is small enough
891to be bounded without losing too much precision. Therefore we only consider
892dependencies on the `non-functional' parts of the state.
893
894The non-functional state is not directly related to the high level
895state and does not influence the functional properties. What can be
896done is to expose key aspects of the non-functional state in the
897source code. We present here the basic intuition in a simplified form:
898the technical details that allow us to handle the general case are
899more complex and can be found in~\cite{paolo}. We add to the source
900code an additional global variable that represents the non-functional
901state and another one that remembers the last few labels emitted. The
902state variable must be updated at every label emission statement,
903using an update function which is computed during static analysis
904too. The update function associates to each label a function from the
905recently emitted labels and old state to the new state. It is computed
906by composing the semantics of every instruction in a basic block and
907restricting it to the non-functional part of the state.
908
909Not all the details of the non-functional state needs to be exposed, and the
910technique works better when the part of state that is required can be summarized
911in a simple data structure. For example, to handle simple but realistic
912pipelines it is sufficient to remember a short integer that encodes the position
913of bubbles (stuck instructions) in the pipeline. In any case, it is not necessary
914for the user to understand the meaning of the state to reason over the properties
915of the
916program. Moreover, at any moment the user, or the invariant generator tools that
917analyse the instrumented source code produced by the compiler, can decide to
918trade precision of the analysis for simplicity by approximating the
919cost with safe bounds that do not depend on the processor state. Interestingly, the functional analysis of
920the code could determine which blocks are executed more frequently in order to
921use more aggressive approximations for the ones that are executed least.
922
923Dependent labeling can also be applied to allow the compiler to duplicate
924blocks that contain labels (e.g. in loop optimisations)~\cite{paolo}. The effect is to assign
925a different cost to the different occurrences of a duplicated label. For
926example, loop peeling turns a loop into the concatenation of a copy of the loop
927body for the first iteration and the conditional execution of the
928loop for successive iterations. Further optimisations will compile the two
929copies of the loop differently, with the first body usually
930taking more time.
931
932By introducing a variable that keeps track of the iteration number, we can
933associate to the label a cost that is a function of the iteration number. The
934same technique works for loop unrolling without modifications: the function will
935assign a cost to the even iterations and another cost to the odd ones. The
936actual work to be done consists of introducing within the source code, and for each
937loop, a variable that counts the number of iterations. The loop optimisation code
938that duplicate the loop bodies must also modify the code to correctly propagate
939the update of the iteration numbers. The technical details are more complex and
940can be found in the CerCo reports and publications. The implementation, however,
941is quite simple (and forms part of our OCaml version of the compiler)
942and the changes to a loop optimising compiler are minimal.
943
944\subsection{Techniques to exploit the induced cost model}
945We now turn our attention to synthesising high-level costs, such as
946the execution time of a whole program.  We consider as our starting point source level costs
947provided by basic labeling, in other words annotations
948on the source code which are constants that provide a sound and sufficiently
949precise upper bound on the cost of executing the blocks after compilation to
950object code.
951
952The principle that we have followed in designing the cost synthesis tools is
953that the synthetic bounds should be expressed and proved within a general
954purpose tool built to reason on the source code. In particular, we rely on the
955Frama-C tool to reason on C code and on the Coq proof-assistant to reason on
956higher-order functional programs.
957
958This principle entails that: 1)
959The inferred synthetic bounds are indeed correct as long as the general purpose
960tool is; 2) there is no limitation on the class of programs that can be handled
961as long as the user is willing to carry on an interactive proof.
962
963Of course, automation is desirable whenever possible. Within this framework,
964automation means writing programs that give hints to the general purpose tool.
965These hints may take the form, say, of loop invariants/variants, of predicates
966describing the structure of the heap, or of types in a light logic. If these
967hints are correct and sufficiently precise the general purpose tool will produce
968a proof automatically, otherwise, user interaction is required.
969
970\paragraph{The Cost plugin and its application to the Lustre compiler.}
971Frama-C \cite{framac} is a set of analysers for C programs with a
972specification language called ACSL. New analyses can be dynamically added
973via a plugin system. For instance, the Jessie plugin allows deductive
974verification of C programs with respect to their specification in ACSL, with
975various provers as back-end tools.
976We developed the CerCo Cost plugin for the Frama-C platform as a proof of
977concept of an automatic environment exploiting the cost annotations produced by
978the CerCo compiler. It consists of an OCaml program which essentially
979takes the following actions: 1) it receives as input a C program, 2) it
980applies the CerCo compiler to produce a related C program with cost annotations,
9813) it applies some heuristics to produce a tentative bound on the cost of
982executing the C functions of the program as a function of the value of their
983parameters, 4) the user can then call the Jessie plugin to discharge the
984related proof obligations.
985In the following we elaborate on the soundness of the framework and the
986experiments we performed with the Cost tool on the C programs produced by a
987Lustre compiler.
988
989\paragraph{Soundness.} The soundness of the whole framework depends on the cost
990annotations added by the CerCo compiler, the synthetic costs produced by the
991cost plugin, the verification conditions (VCs) generated by Jessie, and the
992external provers discharging the VCs. The synthetic costs being in ACSL format,
993Jessie can be used to verify them. Thus, even if the added synthetic costs are
994incorrect (relatively to the cost annotations), the process as a whole is still
995correct: indeed, Jessie will not validate incorrect costs and no conclusion can
996be made about the WCET of the program in this case. In other terms, the
997soundness does not really depend on the action of the cost plugin, which can in
998principle produce any synthetic cost. However, in order to be able to actually
999prove a WCET of a C function, we need to add correct annotations in a way that
1000Jessie and subsequent automatic provers have enough information to deduce their
1001validity. In practice this is not straightforward even for very simple programs
1002composed of branching and assignments (no loops and no recursion) because a fine
1003analysis of the VCs associated with branching may lead to a complexity blow up.
1004\paragraph{Experience with Lustre.} Lustre is a data-flow language for programming
1005synchronous systems, with a compiler which targets C. We designed a
1006wrapper for supporting Lustre files.
1007The C function produced by the compiler implements the step function of the
1008synchronous system and computing the WCET of the function amounts to obtain a
1009bound on the reaction time of the system. We tested the Cost plugin and the
1010Lustre wrapper on the C programs generated by the Lustre compiler. For programs
1011consisting of a few hundred lines of code, the cost plugin computes a
1012WCET and Alt-Ergo is able to discharge all VCs automatically.
1013
1014\paragraph{Handling C programs with simple loops.}
1015The cost annotations added by the CerCo compiler take the form of C instructions
1016that update a fresh global variable called the cost variable by a constant.
1017Synthesizing a WCET of a C function thus consists of statically resolving an
1018upper bound of the difference between the value of the cost variable before and
1019after the execution of the function, i.e. finding the instructions
1020that update the cost variable and establish the number of times they are passed
1021through during the flow of execution. To perform the analysis the plugin
1022makes the following assumptions on the programs:
10231) there are no recursive functions;
10242) every loop must be annotated with a variant. The variants of `for' loops are
1025automatically inferred.
1026
1027The plugin proceeds as follows.
1028First the call graph of the program is computed.
1029Then the computation of the cost of the function is performed by traversing its
1030control flow graph. If the function $f$ calls the function $g$ 
1031then the function $g$ 
1032is processed before the function $f$. The cost at a node is the maximum of the
1033costs of the successors.
1034In the case of a loop with a body that has a constant cost for every step of the
1035loop, the cost is the product of the cost of the body and of the variant taken
1036at the start of the loop.
1037In the case of a loop with a body whose cost depends on the values of some free
1038variables, a fresh logic function $f$ is introduced to represent the cost of the
1039loop in the logic assertions. This logic function takes the variant as a first
1040parameter. The other parameters of $f$ are the free variables of the body of the
1041loop. An axiom is added to account the fact that the cost is accumulated at each
1042step of the loop.
1043The cost of the function is directly added as post-condition of the function.
1044
1045The user can influence the annotation by two different means:
10461) by using more precise variants;
10472) by annotating functions with cost specifications. The plugin will use this cost
1048for the function instead of computing it.
1049\paragraph{C programs with pointers.}
1050When it comes to verifying programs involving pointer-based data structures,
1051such as linked lists, trees, or graphs, the use of traditional first-order logic
1052to specify, and of SMT solvers to verify, shows some limitations. Separation
1053logic is an elegant alternative. It is a program logic
1054with a new notion of conjunction to express spatial heap separation. Bobot has
1055recently introduced automatically generated separation
1056predicates to simulate separation logic reasoning in the Jessie plugin where the specification language, the verification condition
1057generator, and the theorem provers were not designed with separation logic in
1058mind~\cite{bobot}. CerCo's plugin can exploit the separation predicates to automatically
1059reason on the cost of execution of simple heap manipulation programs such as an
1060in-place list reversal.
1061
1062\section{Conclusions and future work}
1063
1064All the CerCo software and deliverables can be found on the CerCo homepage at~\url{http://cerco.cs.unibo.it}.
1065
1066The results obtained so far are encouraging and provide evidence that
1067it is possible to perform static time and space analysis at the source level
1068without losing accuracy, reducing the trusted code base and reconciling the
1069study of functional and non-functional properties of programs. The
1070techniques introduced seem to be scalable, cover both imperative and
1071functional languages and are compatible with every compiler optimisation
1072considered by us so far.
1073
1074To prove that compilers can keep track of optimisations
1075and induce a precise cost model on the source code, we targeted a simple
1076architecture that admits a cost model that is execution history independent.
1077The most important future work is dealing with hardware architectures
1078characterized by history dependent stateful components, like caches and
1079pipelines. The main issue is to assign a parametric, dependent cost
1080to basic blocks that can be later transferred by the labeling approach to
1081the source code and represented in a meaningful way to the user. The dependent
1082labeling approach that we have studied seems a promising tool to achieve
1083this goal, but more work is required to provide good source level
1084approximations of the relevant processor state.
1085
1086Other examples of future work are to improve the cost invariant
1087generator algorithms and the coverage of compiler optimizations, to combining
1088the labeling approach with the type and effect discipline of~\cite{typeffects}
1089to handle languages with implicit memory management, and to experiment with
1090our tools in the early phases of development. Larger case studies are also necessary
1091to evaluate the CerCo's prototype on realistic, industrial-scale programs.
1092
1093% \bibliographystyle{splncs}
1094\bibliography{fopara13}
1095% \begin{thebibliography}{19}
1096%
1097% \bibitem{survey} \textbf{A Survey of Static Program Analysis Techniques}
1098% W.~W\"ogerer. Technical report. Technische Universit\"at Wien 2005
1099%
1100% \bibitem{cerco} \textbf{Certified Complexity}. R.M. Amadio, A. Asperti, N. Ayache,
1101% B. Campbell, D. P. Mulligan, R. Pollack, Y. Regis-Gianas, C. Sacerdoti Coen, I.
1102% Stark, in Procedia Computer Science, Volume 7, 2011, Proceedings of the 2 nd
1103% European Future Technologies Conference and Exhibition 2011 (FET 11), 175-177.
1104%
1105% \bibitem{labeling} \textbf{Certifying and Reasoning on Cost Annotations in C
1106% Programs}, N.  Ayache, R.M. Amadio, Y.R\'{e}gis-Gianas, in Proc. FMICS, Springer
1107% LNCS
1108% 7437: 32-46, 2012.
1109% %, DOI:10.1007/978-3-642-32469-7\_3.
1110%
1111% \bibitem{labeling2} \textbf{Certifying and reasoning on cost annotations of
1112% functional programs}.
1113% R.M. Amadio, Y. R\'{e}gis-Gianas. Proceedings of the Second international conference
1114% on Foundational and Practical Aspects of Resource Analysis FOPARA 2011 Springer
1115% LNCS 7177:72-89, 2012.
1116%
1117% \bibitem{compcert} \textbf{Formal verification of a realistic compiler}. X. Leroy,  In Commun. ACM 52(7), 107–115, 2009.
1118%
1119% \bibitem{framac} \textbf{Frama-C user manual}. L. Correnson, P. Cuoq, F. Kirchner, V. Prevosto, A. Puccetti, J. Signoles,
1120% B. Yakobowski. in CEA-LIST, Software Safety Laboratory, Saclay, F-91191,
1121% \url{http://frama-c.com/}.
1122%
1123% \bibitem{paolo} \textbf{Indexed Labels for Loop Iteration Dependent Costs}. P.
1124% Tranquilli, in Proceedings of the 11th International Workshop on Quantitative
1125% Aspects of Programming Languages and Systems (QAPL 2013), Rome, 23rd-24th March
1126% 2013, Electronic Proceedings in Theoretical Computer Science, to appear in 2013.
1127%
1128% \bibitem{separation} \textbf{Intuitionistic reasoning about shared mutable data
1129% structure} J.C. Reynolds. In Millennial Perspectives in Computer Science,
1130% pages 303–321, Houndsmill, Hampshire, 2000. Palgrave.
1131%
1132% \bibitem{lustre} \textbf{LUSTRE: a declarative language for real-time
1133% programming}
1134% P. Caspi, D. Pilaud, N. Halbwachs, J.A. Plaice. In Proceedings of
1135% the 14th ACM SIGACT-SIGPLAN symposium on Principles of programming languages ACM
1136% 1987.
1137%
1138% \bibitem{correctness} \textbf{On the correctness of an optimising assembler for
1139% the intel MCS-51 microprocessor}.
1140%   D. P. Mulligan, C. Sacerdoti Coen. In Proceedings of the Second
1141% international conference on Certified Programs and Proofs, Springer-Verlag 2012.
1142%
1143% \bibitem{proartis} \textbf{PROARTIS: Probabilistically Analysable Real-Time
1144% Systems}, F.J. Cazorla, E. Qui\~{n}ones, T. Vardanega, L. Cucu, B. Triquet, G.
1145% Bernat, E. Berger, J. Abella, F. Wartel, M. Houston, et al., in ACM Transactions
1146% on Embedded Computing Systems, 2012.
1147%
1148% \bibitem{embounded} \textbf{The EmBounded project (project paper)}. K. Hammond,
1149% R. Dyckhoff, C. Ferdinand, R. Heckmann, M. Hofmann, H. Loidl, G. Michaelson, J.
1150% Serot, A. Wallace, in Trends in Functional Programming, Volume 6, Intellect
1151% Press, 2006.
1152%
1153% \bibitem{matita}
1154% \textbf{The Matita Interactive Theorem Prover}.
1155% A. Asperti, C. Sacerdoti Coen, W. Ricciotti, E. Tassi.
1156% 23rd International Conference on Automated Deduction, CADE 2011.
1157%
1158% \bibitem{typeffects} \textbf{The Type and Effect Discipline}. J.-P. Talpin,
1159%  P. Jouvelot.
1160%   In Proceedings of the Seventh Annual Symposium on Logic in Computer Science
1161% (LICS '92), Santa Cruz, California, USA, June 22-25, 1992.
1162% IEEE Computer Society 1992.
1163%
1164% \bibitem{stateart} \textbf{The worst-case execution-time problem overview of
1165% methods
1166% and survey of tools.} R. Wilhelm et al., in  ACM Transactions on Embedded
1167% Computing Systems, 7:1–53, May 2008.
1168%
1169% %\bibitem{proartis2} \textbf{A Cache Design for Probabilistic Real-Time
1170% % Systems}, L. Kosmidis, J. Abella, E. Quinones, and F. Cazorla, in Design,
1171% % Automation, and Test in Europe (DATE), Grenoble, France, 03/2013.
1172%
1173% \end{thebibliography}
1174
1175
1176%\bibliography{fopara13.bib}
1177
1178\end{document}
Note: See TracBrowser for help on using the repository browser.