A CIL Tutorial - Department of Computer Science - ETH Zürich

A CIL Tutorial - Department of Computer Science - ETH Zürich A CIL Tutorial - Department of Computer Science - ETH Zürich

29.01.2014 Views

CHAPTER 3. DATAFLOW ANALYSIS 22 static analysis. Now is a good time to take a look in dataflow.mli at the signature of the module that we'll be implementing, and what the functions of the module mean. Additionally, the Dataflow module is well documented in the main CIL documentation. 3.1 tut3.ml The dataow analysis here is a common textbook example for abstract interpretation, an even/odd analysis. First, we'll dene types and operations over the abstract state of the program. Then, we'll apply the functor. Following this, we'll write some boilerplate code for accessing the results of the analysis in an AST visitor. It should be straightforward to repurpose the code in this tutorial for many other kinds of dataow analysis, so feel free to use it as a starting point. For dataow analysis in the backwards direction, there is also a BackwardsDataFlow functor in the Dataflow module. module IH = Inthash (∗ An int → α hashtable library ∗) module DF = Dataflow (∗ CIL's dataow analysis library ∗) When debug is true, the dataow library emints out lots of debugging information. let debug = ref false 3.1.1 Type Denitions The abstract state for the analysis is a mapping from local variables of integral type to one of the oekind constructors. When a variable is mapped to one of these kinds, it has the following meaning: • Top The variable could be either odd or even. • Even The variable is an even integer. • Odd The variable is an odd integer. • Bottom The variable is uninitialized. type oekind = Top | Odd | Even | Bottom We'll use association lists to represent the mapping. An element of the mapping for a variable vi : varinfo is like: (vi.vid, (vi, kind)). We'll also need some utility functions for examining and manipulating the mappings.

CHAPTER 3. DATAFLOW ANALYSIS 23 Coding Hint: Whenever you dene a new type t, write a string of t function, and if it makes sense, a t of string function as well. Here, we have to in order to implement one of the functions we need for the ForwardsTransfer signature, but it's also a good idea in general for at least two reasons. First, they come in handy for debugging, and second, they give you a sense of how easy the types you've dened will be to program with. type varmap = int × (varinfo × oekind) let id of vm (vm : varmap) : int = fst vm let vi of vm (vm : varmap) : varinfo = vm | > snd | > fst let kind of vm (vm : varmap) : oekind = vm | > snd | > snd 3.1.2 Functions for pretty printing the state One of the functions we'll need to dene for the ForwardsDataFlow functor is a function to prettyprint the abstract state. In particular, we must dene a function that turns the abstract state into an instance of type Pretty.doc. Functions for constructing objects of this type are dened in the module Pretty in pretty.ml. For now, though, we'll just turn our abstract state into an OCaml string, and then use the function Pretty.text : string → doc to obtain a doc. let string of oekind (k : oekind) : string = match k with | Top → "Top" | Odd → "Odd" | Even → "Even" | Bottom → "Bottom" The string of varmap function converts a varmap tuple to a string: let string of varmap (vm : varmap) : string = let vi = vi of vm vm in "("¢vi.vname¢", "¢(vm | > kind of vm | > string of oekind)¢")" The string of varmap list converts a list of varmaps into a comma-separated list: let string of varmap list (vml : varmap list) : string = vml |> L.map string of varmap |> String.concat ", "

CHAPTER 3. DATAFLOW ANALYSIS 23<br />

Coding Hint: Whenever you dene a new type t, write a string <strong>of</strong> t function,<br />

and if it makes sense, a t <strong>of</strong> string function as well. Here, we have to<br />

in order to implement one <strong>of</strong> the functions we need for the ForwardsTransfer<br />

signature, but it's also a good idea in general for at least two reasons. First,<br />

they come in handy for debugging, and second, they give you a sense <strong>of</strong> how<br />

easy the types you've dened will be to program with.<br />

type varmap = int × (varinfo × oekind)<br />

let id <strong>of</strong> vm (vm : varmap) : int = fst vm<br />

let vi <strong>of</strong> vm (vm : varmap) : varinfo = vm | > snd | > fst<br />

let kind <strong>of</strong> vm (vm : varmap) : oekind = vm | > snd | > snd<br />

3.1.2 Functions for pretty printing the state<br />

One <strong>of</strong> the functions we'll need to dene for the ForwardsDataFlow functor is a function to prettyprint<br />

the abstract state. In particular, we must dene a function that turns the abstract state into<br />

an instance <strong>of</strong> type Pretty.doc. Functions for constructing objects <strong>of</strong> this type are dened in the<br />

module Pretty in pretty.ml. For now, though, we'll just turn our abstract state into an OCaml<br />

string, and then use the function Pretty.text : string → doc to obtain a doc.<br />

let string <strong>of</strong> oekind (k : oekind) : string =<br />

match k with<br />

| Top → "Top"<br />

| Odd → "Odd"<br />

| Even → "Even"<br />

| Bottom → "Bottom"<br />

The string <strong>of</strong> varmap function converts a varmap tuple to a string:<br />

let string <strong>of</strong> varmap (vm : varmap) : string =<br />

let vi = vi <strong>of</strong> vm vm in<br />

"("¢vi.vname¢", "¢(vm | > kind <strong>of</strong> vm | > string <strong>of</strong> oekind)¢")"<br />

The string <strong>of</strong> varmap list converts a list <strong>of</strong> varmaps into a comma-separated list:<br />

let string <strong>of</strong> varmap list (vml : varmap list) : string =<br />

vml<br />

|> L.map string <strong>of</strong> varmap<br />

|> String.concat ", "

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!