\documentclass[11pt]{article}
\usepackage{ifthen}
\usepackage{alltt}
% \usepackage{indentfirst}
\usepackage{latexsym}
\usepackage[pdftex]{graphicx}
\usepackage{gdefs}
% \usepackage{logdef}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{setspace}
\usepackage{rotating}
\usepackage{longtable}
\usepackage{hhline}
\usepackage{refs}
\usepackage{graph}
\usepackage{changebar}
\usepackage{array}
\usepackage{wrapfig}
\usepackage[small,compact]{titlesec}

\usepackage{pgf}
\usepackage{stmaryrd}
\usepackage[latin1]{inputenc}
\usepackage{verbatim}
\usepackage{lmodern}

\usepackage{tikz}
\usetikzlibrary{arrows, automata, decorations.pathmorphing, backgrounds, positioning, fit, matrix, shapes, patterns, calc}



\usepackage{tweaklist}
% this sets the spacings in the itemize environment
\renewcommand{\itemhook}{\setlength{\topsep}{0pt}%
  \setlength{\itemsep}{0pt}%
  \setlength{\parsep}{0ex}%
}

% this sets the spacings in the enumerate environment
\renewcommand{\enumhook}{\setlength{\topsep}{0pt}%
  \setlength{\itemsep}{0pt}%
  \setlength{\parsep}{0ex}%
}

% this sets the spacings in the description environment
\renewcommand{\descripthook}{\setlength{\topsep}{0pt}%
  \setlength{\itemsep}{0pt}%
  \setlength{\parsep}{0ex}%
}

\setlength{\topmargin}{0.0in}
\setlength{\headheight}{0.0in}
\setlength{\headsep}{0.0in}
\setlength{\textwidth}{6.5in}
\setlength{\oddsidemargin}{0.0in}
\setlength{\evensidemargin}{0.0in}
\setlength{\textheight}{9.0in}

\setcounter{topnumber}{5}
\def\topfraction{0.99}
\def\textfraction{0.05}
\def\floatpagefraction{0.9}
\setcounter{bottomnumber}{5}
\def\bottomfraction{0.99}
\setcounter{totalnumber}{10}
\def\dbltopfraction{0.99}
\def\dblfloatpagefraction{0.8}
\setcounter{dbltopnumber}{5}

\setlength{\marginparwidth}{.95in}
\let\oldmarginpar\marginpar
\renewcommand\marginpar[1]{\-\oldmarginpar[\raggedleft\footnotesize #1]%
{\raggedright\footnotesize #1}}

\let\oldthebibliography=\thebibliography
  \let\endoldthebibliography=\endthebibliography
  \renewenvironment{thebibliography}[1]{%
    \begin{oldthebibliography}{#1}%
      \setlength{\parskip}{0ex}%
      \setlength{\itemsep}{0ex}%
  }%
  {%
    \end{oldthebibliography}%
  }


\newcommand{\Kill}{\textit{Kill}}
\newcommand{\Gen}{\textit{Gen}}
\newcommand{\Id}{\textit{Id}}
\newcommand{\CallSites}{\textit{CallSites}}
\newcommand{\CallIn}{\textit{CallIn}}
\newcommand{\CallOut}{\textit{CallOut}}
\newcommand{\Ret}{\textit{Ret}}
\newcommand{\unbalLeft}{\textit{unbalLeft}}
\newcommand{\matched}{\textit{matched}}
\newcommand{\IVP}{\textit{IVP}}

\newcommand{\pf}{\textit{pf}}
\newcommand{\spf}{\textit{spf}}
\newcommand{\apf}{\textit{apf}}
\newcommand{\SM}{\textit{SM}}
\newcommand{\SSSD}{\textit{SSSD}}
\newcommand{\ESSSD}{\textit{ESSSD}}
\newcommand{\EQ}{\textit{EQ}}
\newcommand{\CS}{\textit{CS}}
\newcommand{\SCS}{\textit{SCS}}
\newcommand{\ECS}{\textit{ECS}}
\newcommand{\EAS}{\textit{EAS}}
\newcommand{\EFAS}{\textit{EFAS}}
\newcommand{\PT}{\textit{PT}}
\newcommand{\APS}{\textit{APS}}
\DeclareMathOperator{\ulambda}{\underline{\lambda}}
\DeclareMathOperator{\op}{\textrm{op}}
\DeclareMathOperator{\extend}{\otimes}
\DeclareMathOperator{\combine}{\oplus}
\DeclareMathOperator{\scomposition}{\tilde{\circ}}
\DeclareMathOperator*{\bigcombine}{\bigoplus}
\DeclareMathOperator*{\bigextend}{\bigotimes}
\DeclareMathOperator*{\Min}{\textrm{\large{Min}}}
\DeclareMathOperator*{\bigcircle}{\bigcirc}
\newcommand{\bbN}{\mathbb{N}}
\newcommand{\bbZ}{\mathbb{Z}}
\newcommand{\len}{\textrm{len}}
\newcommand{\weight}{\textrm{weight}}
\newcommand{\pathWeight}{\textrm{pathWeight}}
\newcommand{\Nodes}{\textrm{Nodes}}
\newcommand{\Edges}{\textrm{Edges}}
\newcommand{\Paths}{\textrm{Paths}}
\newcommand{\Store}{\textrm{Store}}
\newcommand{\AStore}{\textrm{AStore}}
\newcommand{\Var}{\textrm{Var}}
\newcommand{\Val}{\textrm{Val}}
\newcommand*{\stacked}[2]{\genfrac{}{}{0pt}{}{#1}{#2}}

\title{Interprocedural Dataflow Analysis, Part I \\
       CS701
}

\author{Thomas Reps \\ \small[Based on notes taken by Sek Cheong on October 15, 2015]}
\date{}

\begin{document}           % End of preamble and beginning of text.

\maketitle
\begin{abstract}
This lecture discusses interprocedural dataflow analysis. We describe
the ``functional approach'' to interprocedural dataflow analysis
pioneered by Sharir and Pnueli \cite{PFA:SP81}, and show some
connections to the kind of path problems discussed in the
previous two lectures.
We will also look at the family of so-called ``gen/kill problems''
because they are the simplest class of problems that helps to provide
some insight on some of the issues that arise in Sharir/Pnueli
algorithm.
\end{abstract}

\section{Pointer Analysis}
\label{Se:PointerAnalysis}

In terms of connecting pieces end-to-end so that one can write a sound analyzer
for a compiler or a bug-finding tool, we are omitting---for now---a key step,
which is what to do about pointers.
The reason for doing so is that pointer-analysis algorithms generally make use of
techniques other than the path problems that I have been discussing.
The method(s) for interprocedural dataflow analysis that I will present
are related to path problems, and I don't want to lose the context that we have
built up.
However, I do want to give you an idea of the kind of information that pointer
analysis supplies.

\paragraph{Statement Normalization.}
A program can contain pointer-manipulation statements like the following ones:
%
\begin{verbatim}
    x = *p;
   *q = y;
\end {verbatim}
%
What do we do about these pointer dereferences?
First, the program is normalized into a form in which all assignment
statements are broken down into uses of four kinds of statements:
%
\begin{verbatim}
    p = &x;
    p = q;
    x = *p;
   *q = y;
\end{verbatim}
%
Note that if we have a statement that is not of this form, such as,
%
\begin{verbatim}
    x = ***q;
\end{verbatim}
%
the analyzer will introduce temporary variables to hold on to
the results of successive pointer-dereference operations, e.g.,
%
\begin{verbatim}
    t1 = *q;
    t2 = *t1;
    x = *t2;
\end{verbatim}
%

\paragraph{Use of Points-To Information.}
Pointer analysis gives us information in the form of $p$ points to
some set of variables, such as $p \mapsto \{ y,z \}$.
The points-to information $p \mapsto \{ y,z \}$ means ``$p$ might
point to $y$ or $p$ might point to $z$.''
In general, we can have zero or more elements in the set;
sometimes we can have thousands of elements in the set
(which is often due to a cascade of imprecision during pointer analysis).
A pointer-analysis algorithm can be either \emph{flow-sensitive} or
\emph{flow-insensitive}.
A flow-sensitive algorithm provides points-to information that is
specific to each point in the program.
A flow-insensitive algorithm is less precise: the flow of control in
the program is ignored, and all points-to information recovered is
treated as holding for each point in the program.\footnote{
  If the use of a flow-insensitive point-to algorithm
  sounds like a strange thing to do, think of it as
  being in the same spirit of type information.
  When we say that a variable has type $\tau$,
  it must have ``$\tau$-like behavior'' throughout
  the program.
  Similarly, when client code uses points-to facts
  obtained with a flow-insensitive algorithm, it
  must operate under the constraint that, e.g.,
  $p \mapsto \{ y,z \}$ holds throughout the program.
}

When the client of point-to analysis is yet another phase of
dataflow analysis, the point-to information is typically
used to (implicitly or explicitly) to treat a pointer-manipulation
statement like $x = *p$ as a non-deterministic choice
among a collection of assignment statements.
For instance, when the points-to information for $p$ is
$p \mapsto \{ y,z \}$, $x = *p$ is transformed to
%
\begin{verbatim}
    if (*)
      x = y;
    else
      x = z;
\end{verbatim}
%
where ``*'' denotes an unknown Boolean value.
If there are more elements in the points-to set, $x = *p$ would be
transformed into a $k$-way non-deterministic choice.

\begin{figure*}
\begin{center}
\begin{tikzpicture}
\draw [pattern=north east lines, pattern color=black] (-2,0) rectangle (-1.2,0.8);
\draw [pattern=north east lines, pattern color=black] (0.2,0.5) rectangle (1,1.3);
\draw [pattern=north east lines, pattern color=black] (1.8,0.3) rectangle (2.6,1.1);

\draw [fill=white, very thin] (-1.2,-1.5) rectangle (-0.4,-0.7);
\draw [fill=white, very thin] (0,-1.2) rectangle (0.8,-0.4);
\draw [fill=white, very thin] (1.3,-1.0) rectangle (2.1,-0.2);

\draw [dashed] (-1.2,0.8) -- (3.8,3.5) node [right] {\texttt{malloc\$a}};
\draw [dashed] (1,1.3) -- (3.8,3.5);
\draw [dashed] (2.6,1.2) -- (3.8,3.5);

\node [cloud, draw, cloud puffs=11,cloud puff arc=120, aspect=2, inner ysep=1em, minimum width=8cm, minimum height=5cm] {};
\end{tikzpicture}
\end{center}
\caption{Depiction of a concrete heap and how its elements relate to
  the summary node \texttt{\&malloc\$a} that would be introduced to
  represent all the storage locations allocated by a statement such as
  ``a: p = malloc(...).''
  The cloud stands for a snapshot of the concrete heap
  nodes---allocated at statement \texttt{a} and elsewhere.
  The shaded boxes represent the storage locations 
  that were allocated at statement \texttt{a}.
  The white boxes represent storage locations that were
  allocated at statements other than \texttt{a} (which
  would be represented by other summary locations.
}
\label{Fi:HeapAllocatedStorage}
\end{figure*}

\paragraph{Handling Heap-Allocated Storage.}
Another thing we need to know about points-to-analysis problems is what
the analyzer does about an allocation statement, such as
%
\begin{verbatim}
    a: p = malloc(...)
\end{verbatim}
%
The analyzer converts this statement into the assignment
of the address of a fictitious variable \texttt{\&malloc\$a}:
%
\begin{verbatim}
    a: p = &malloc$a;
\end{verbatim}
%
Here the letter \texttt{a} in \texttt{\&malloc\$a} matches the
original label \texttt{a} of the statement.
This fictitious variable summarizes all storage locations allocated at
program point \texttt{p}.
In \figref{HeapAllocatedStorage}, the cloud stands for a snapshot of
the concrete heap nodes---allocated at statement \texttt{a} and
elsewhere.
The shaded boxes represent the storage locations that were allocated
at statement \texttt{a}.
The white boxes represent storage locations that were allocated at
statements other than \texttt{a} (which would be represented by other
summary locations.

This method is basically a simple way of finitizing the {\it a priori}
unbounded amount of storage that might be allocated at statement
\texttt{a} by mapping it to some bounded-size set of descriptors.

\section{Path Problems}

\subsection{An Anomaly}
\label{Se:AnAnomaly}

\begin{figure*}
\begin{center}
  \begin{tikzpicture} [node distance=3cm,->]
	\node (A) {};
	\node (B) [above right=1.5cm and 1cm of A] {$m_1$};
	\node (B2)[above right=0.8cm and 1cm of A] {$m_2$};
	\node (Dot1)[below right=-0.6cm and 1cm of A] {$\cdot$};
	\node (Dot2)[below right=-0.2cm and 1cm of A] {$\cdot$};
	\node (Dot3)[below right=0.2cm and 1cm of A] {$\cdot$};
	\node (C) [below right=1.5cm and 1cm of A] {$m_n$};
	\node (D) [below right of = B] {$n$};
	\path (B) edge node [above=.2cm] {$M^\sharp$} (D);
	\path (B2) edge node[below=.0cm] {} (D);
	\path (C) edge node [above=.2cm] {} (D);
  \end{tikzpicture}
\end{center}
\caption{Equational abstract semantics.}
\label{Fi:EAS}
\end{figure*}

Last lecture, there was a small anomaly in our use of the path-problem
framework that I introduced and discussed in previous lectures.
The goal that I had articulated was to work through a sequence of
problems so that we had a unified picture of dataflow-analysis
problems as path problems.
We started out with the single-source shortest distance problem
$(\SSSD)$, in terms of the operators $+$ and $\min$.
I then introduced more abstract---but unbiased---terminology;
I expressed everything in terms of two binary operators,
extend ($\extend$) and combine ($\combine$).
However, there was one place where I did not quite manage to pull off
the promised grand unification:
when we finally got to intraprocedural (single-procedure) dataflow
analysis, the equational view was expressed as the following equation
(see \figref{EAS}):

\begin{equation}
  \label{Eq:EAS}
  \EAS[s,n] \eqdef
  \begin{cases}
    \top                                           & \text{if $n = s$} \\
    {\displaystyle \bigcombine_{\B{m,n}\in \Edges}} \A{M}(\B{m,n})(\EAS[s,m]) & \text{otherwise}
  \end{cases}
\end{equation}
where $s$ is the start node, and $\top$ is the value of $\AStore$ that
represents all stores in $\Store$.

Note that \eqref{EAS} is almost of the desired form, but not quite:
in particular, the second line of \eqref{EAS} uses \emph{function application}
(i.e., $\A{M}(\B{m,n})(\EAS[s,m])$) rather than the \emph{extend operation}.
The reason I say that we \emph{almost} have the desired form because
extend is the reversal of function composition, and function
application is closely related to function composition.\footnote{
  The extend operation, which is the reversal of function composition,
  is just a slight variant of notation with which you are already familiar---namely,
  think of extend as the UNIX pipe operator!
  As we go along a path, we have a collection of operators that
  we successively pipe into each other:
  \[
    \weight(e_1) \extend \weight(e_2) \extend \ldots \extend \weight(e_k)
    =
    \weight(e_1) \mid \weight(e_2) \mid \ldots \mid \weight(e_k).
  \]
}
One of the things we will do today is to fix this minor glitch.

\subsection{Declarative View}

Before changing the equational view, let us go back and review the declarative view
for a moment.
The \emph{abstract path semantics}, denoted by $\APS[s,n]$, is defined as follows:
\begin{equation}
  \label{Eq:APS}
  \APS[s,n] \eqdef \bigcombine_{p\in \Paths(s,n)} \apf_p(\top),
\end{equation}
where the \emph{abstract path transfer} function for path $p = e_1,e_2, \ldots, e_k$ is
defined as
\[
  \apf_p \eqdef \A{M}(e_1)\extend \A{M}(e_2) \extend \ldots \extend \A{M}(e_k),
\]
and $\bigcombine$ is the combine operator of the abstract domain.
Recall what is going on here:
$\apf_p(\top)$ is the path function associated with path $p$ from 
start node $s$ to $n$, applied to the abstract store that represents
all possible stores that can be supplied as the initial store at $s$
(i.e., $\top$).

\eqref{APS} handles the case of \emph{single-procedure} dataflow
analysis, and the question is how it should be generalized for the
\emph{multiple-procedure} case.
Part of the machinery that we need for handling the multiple-procedure
case is exactly the fix to the glitch identified in
\sectref{AnAnomaly}---so back to the equational view!

\subsection{Equational View}

\begin{figure*}
\begin{center}
\begin{tikzpicture}

\draw [thick] (0,0) circle [radius=.1] node [above] (enter) {$e$};
\draw [thick] (2,0) circle [radius=.1] node [above] (exit) {$x$};

\draw [->, black, thick]   (enter) to[out=-145,in=-35, distance=8.5cm ] (exit);
\draw [->, decorate, decoration=snake]   (enter) to[out=-125,in=-55, distance=5.5cm ] (exit);
\draw [->, decorate, decoration=snake]   (enter) to[out=-105,in=-75, distance=3.5cm ] (exit);

\end{tikzpicture}
\end{center}
\caption{
}
\label{Fi:CFG}
\end{figure*}

Let us now return to the equational view (\eqref{EAS}), and fix the
glitch pointed out in \sectref{AnAnomaly}.
The fix is to lift \eqref{EAS} from \emph{values} to \emph{functions},
as follows:
\begin{equation}
  \label{Eq:EFAS}
  \begin{array}{@{\hspace{0ex}}r@{\hspace{1ex}}c@{\hspace{1ex}}l@{\hspace{0ex}}}
    \EFAS[s,n]  & = & \Id \\
    \EFAS[s,n]  & = & \bigcombine_{\B{m,n}\in \Edges} M^\sharp_{(m,n)} \circ \EFAS(m),
  \end{array}
\end{equation}
\eqref{EFAS} will be explained in more detail below.

For the single-procedure case, a CFG looks like the graph
depicted in \figref{CFG}.
I'll use $e$ to denote what we have been calling the start node.
(In the multiple-procedure case, each procedure's CFG will have
an \emph{entry node}, whence the use of ``$e$''.)
We use $x$ to represent the CFG's \emph{exit} node.
In the graphical notation used in \figref{CFG},
a squiggly line from $e$ to $x$ will denote a path---or sometimes a
set of paths---that start at $3$ and proceed through the procedure to
$x$.

\begin{figure*}
\begin{center}
\begin{tikzpicture}

\draw [thick] (0,0) circle [radius=.1] node [above] (e) {$e$};
\draw [thick] (2,0) circle [radius=.1] node [above] (x) {$x$};
\draw [thick] (0,-2) circle [radius=.1] node [above] (c) {$c$};
\draw [red] (2,-1) circle [radius=.1] node [above] (z) {$z$};
\draw [thick] (2,-2) circle [radius=.1] node [above] (r) {$r$};
\draw [thick] (0,-4) circle [radius=.1] node [above] (ep) {$e'$};
\draw [thick] (2,-4) circle [radius=.1] node [above] (xp) {$x'$};
\draw [black, thin]   (e) to[bend right=60] (c);
\draw [black, thin]   (x) to[bend left=60] (r);
\draw [->, black, dashed]   (c) to[bend right=60] (ep);
\draw [->, black, dashed]   (xp) to[bend right=60] (r);
\draw [->, black]   (r) to (z);
\draw [black]   (ep) to[out=-145,in=-35, distance=3.5cm ]  (xp);

\end{tikzpicture}
\end{center}
\caption{Interprocedural control-flow graph (ICFG).}
\label{Fi:ICFG}
\end{figure*}

The graph shown in \figref{ICFG} depicts the simplest
multiple-procedure case: a caller calling a single callee.
We call such a graph an \emph{interprocedural control-flow graph},
or \emph{ICFG}.
We split each call site in the caller into two separate and distinct nodes:
\emph{call-node} $c$ represents the call;
\emph{return-node} $r$ represents where control returns to in the caller
after the callee finishes execution.
$e'$ is the entry node of the callee and $x'$ is the exit node of the callee.

Node $r$ represents an artificial ``landing pad'' for transferring control
back to the caller.
At the machine-code level, the callee returns control to the
instruction that follows the call instruction in the caller.
Our diagrams are an idealized model;
the node that represents the first real action in the caller
after control returns from the call will be modeled by the
successor of $r$ (i.e., node $z$ in \figref{ICFG}).

The edge $(c,e')$ is called a \emph{linkage-in} edge;
the edge $(x',r)$ is called a \emph{linkage-out} edge.

\begin{figure*}
\begin{center}
\begin{tabular}{c@{\hspace{5ex}}c}
  \includegraphics[width=.35\textwidth]{figures/EFAS-general.eps}
  &
  \includegraphics[width=.35\textwidth]{figures/EFAS-initial.eps}
  \\
  (a) & (b)
\end{tabular}
\end{center}
  \vspace*{-2.0ex}
\caption{Depiction of the two cases in \eqref{EAS}.}
\label{Fi:DepictionOfEAS}
\end{figure*}

\eqref{EFAS} can be understood using two pictures, as shown in \figref{DepictionOfEAS}.
\figref{DepictionOfEAS}(a) looks similar to the picture used in the Oct.\ 13, 2015
lecture to illustrate the equational formulation of the $\SSSD$ problem.
In \figref{DepictionOfEAS}(a), we have $k$ predecessors of node $n$, $m_1, \ldots, m_k$,
and the edges from each $m_i$ to $n$ is labeled with a transformer function $\A{M}(m_i,n)$.
Each (solid black) double-edged arrow represents an $\EFAS$ value, which itself is a
transformer function.
This information is used in \eqref{EFAS} to create the function that
represents the transformation from $e$ to $n$ by composing appropriate
pairs of $\A{M}$ and $\EFAS$ functions and combining the results:
\[
  \EFAS[s,n] = \bigcombine_{\B{m,n}\in \Edges} \A{M}_{(m,n)} \circ \EFAS(m).
\]
The result is represented in \figref{DepictionOfEAS}(a) by the (dashed red)
double-edged arrow from $e$ to $n$.

\figref{DepictionOfEAS}(b) shows how the process of creating $\EFAS$ values
(i.e., double-ruled lines) gets started, namely, we start with a
single double-ruled line from $e$ to $e$, which represents the
$0$-length path from $e$ to itself.
The transformation associated with this path is the identity
transformation, denoted by $\Id$.

Note how this approach is a different method for intraprocedural dataflow analysis.
Earlier, we performed a successive-approximation method on
\emph{dataflow values};
in contrast, \eqref{EFAS} and \figref{DepictionOfEAS} perform a
successive-approximation method on \emph{dataflow transformers}.

Finally, because compose is the reverse of extend, we can rewrite
\eqref{EFAS} as follows, using the extend operator:
\begin{equation}
  \label{Eq:EFASWithExtend}
  \begin{array}{@{\hspace{0ex}}r@{\hspace{1ex}}c@{\hspace{1ex}}l@{\hspace{0ex}}}
    \EFAS[s,n]  & = & \Id \\
    \EFAS[s,n]  & = & \bigcombine_{\B{m,n}\in \Edges}  \EFAS(m) \extend M^\sharp_{(m,n)}.
  \end{array}
\end{equation}

Note how \eqref{EFASWithExtend} fixes up the anomaly discussed in
\sectref{AnAnomaly};
\eqref{EFASWithExtend} is now of the desired form for a path problem!

It must be pointed out that there is just a small amount of sleight-of-hand
here.
In \eqref{EAS}, the combine operation ($\combine$) is a binary operation
on \emph{dataflow values}, whereas in
\eqrefs{EFAS}{EFASWithExtend} $\combine$ is now a binary operation on
\emph{dataflow transformers} (i.e., functions from dataflow values to dataflow
values).

What do we mean by a ``combine operation on functions?''
Basically, the function $f_1 \combine f_2$ constructed by combining
two functions $f_1$ and $f_2$ maps a value in the domain-space into
two values in the range-space, and takes the combine of those values
in the range-space:
\[
  (f_1 \combine f_2)(v) = f_1(v) \combine f_2(v).
\]
For instance, suppose that $f_1$ and $f_2$ operate on sets:
\[
  f_1 \eqdef \lambda S.S \cup \{ a,b \}
\]
and
\[
  f_2 \eqdef \lambda S.S \cup \{ b, c \}.
\]
Then, assuming that the combine operation on values is set-union, we have
\[
  (f_1 \combine f_2)(S) = f_1(S) \combine f_2(S) = S \cup \{ a,b,c \}.
\]

\section{Gen/Kill Problems}
\label{Se:GenKillProblems}

First of all, it probably would have been better if this class of dataflow-analysis
problems were called kill/gen problems, rather than gen/kill problems.
As we will see, the order in which operations occur in the dataflow transformers
is that a ``kill'' operation  comes first, followed by a ``gen'' operation.
No matter---it is conventional to call them \emph{gen/kill problems}.
Many simple dataflow-analysis problems are expressible by gen/kill functions,
which is where this family of problems gets their name.
To be concrete, we will illustrate one problem that is useful for static 
taint analysis, namely, the \emph{reaching-definitions problem}.

\begin{figure*}
\begin{center}
  \includegraphics[width=.35\textwidth]{figures/rdefs-example.eps}
\end{center}
\caption{An example to illustrate the reaching-definitions problem.}
\label{Fi:RDefsExample}
\end{figure*}

Consider the example shown in \figref{RDefsExample}.
There are several statements that assign to variable $x$---those at
labels $a$, $b$, and $c$.
There is also a use of $x$ in the statement $y = x$ shown at the bottom.
Our goal is to gather up information so that what we know at a node $n$
reflects what may hold just before $n$ executes.
In this case, we want to know the answer to the question,
``For each node $n$, what are the program points that might have assigned
into $x$ the value that $x$ holds just before $n$ executes?''
(Actually, we want to know the answer to this question for each
of the program variables in scope at each node $n$.)

Here is how we can formalize this problem as a gen/kill problem.
In the dataflow transformer for program-point $p$, the input set $S$ is transformed by
(i) subtract some set $\Kill_p$ from $S$, and
(ii) union the result of (i) with some other set $\Gen_p$.
In other words, each dataflow transformer has the form
\[
  \lambda S. (S - \Kill_p) \cup \Gen_p,
\]
where $\Kill_p$ and $\Gen_p$ are constant sets associated with program-point $p$.
With different points we can have different functions.
The universe of gen/kill functions is
\[
  F \eqdef \{ \lambda S.(S - K) \cup G \mid K \subseteq A, G \subseteq A \},
\]
where $A$ is some universe of dataflow facts.
Note that $A$ typically depends on the program being analyzed, so it
would be more precise to refer to $A_{\textrm{prog}}$ rather than $A$.
We will leave off the subscript $\textrm{prog}$, except for emphasis.

In the case of reaching-definitions, $A_{\textrm{prog}}$ is defined as follows:\footnote{
  When there are fictitious variables of the form \texttt{\&malloc\$a} introduced
  for the purpose of points-to analysis in the presence of heap-allocated storage,
  we need to say
  $A_{\textrm{prog}} \eqdef \{ \B{v:l} \mid \text{variable $v$ \emph{may} be assigned to at $l$}\}$.
}
\[
  A_{\textrm{prog}} \eqdef \{ \B{v:l} \mid \text{variable $v$ is assigned to at $l$} \}.
\]
Note that in the absence of heap-allocated storage,
\[
  |A_{\textrm{prog}}| \approx \text{number of nodes in the CFG}.
\]

Returning to \figref{RDefsExample}, at node $b$, the kill set $\Kill_b $
is
\[ 
  K_b \eqdef \{ \B{x:l} | \text{$x$ is assigned to at $l$} \};
\]
the gen set $\Gen_b$ is $\{ \B{x:b} \}$; and the
dataflow transformer at $b$ is
$\lambda S.(S - \Kill_b) \cup \Gen_b$.
Note that $\Kill_b$ actually removes $\B{x:b}$ from $S$;
however, that is OK because $\Gen_b$ unions $\{ \B{x:b} \}$
into the answer set.

In terms of a representation scheme for gen/kill functions, a gen/kill
function $\lambda S.(S - K) \cup G$ can be represented by a pair of
sets $\B{K,G}$.
In \sectrefs{Combine}{Extend}, we show how to perform combine and
extend using such function representations.

\subsection{Combine}
\label{Se:Combine}

Suppose that we have two functions
$f_1 \eqdef \lambda S.(S-K_1) \cup G_1$ and $f_2 \eqdef \lambda T.(T-K_2) \cup G_2$,
represented by the pairs of sets $\B{K_1,G_1}$ and $\B{K_2,G_2}$, respectively.
Then we want to determine the appropriate function of $K_1$, $G_1$, $K_2$, and $G_2$
that should be performed to create the representation of the function
\[
  f_3 = (\lambda S.(S-K_1) \cup G_1) \combine (\lambda S.(S-K_2) \cup G_2).
\]
The picture looks like the following: 

\begin{center}
\begin{tikzpicture}
\draw [thick] (0,0) circle [radius=.24] node (e) {$e$};
\draw [thick] (0,-2.75) circle [radius=0] node [above] (c) {$\combine$};
\draw [thick, color=black] (0,-3) circle [radius=.24] node (x) {$n$};
%\draw[->] (e) to[bend right=60] node[left] {$f_1$} (x);
%\draw[->] (e) to[bend left=60] node[right] {$f_2$} (x);
\draw[->, decorate, decoration=snake] (e) to[bend right=50] node[left] {$f_1~~$} (x);
\draw[->, decorate, decoration=snake] (e) to[bend left=50] node[right] {$~~f_2$} (x);
\end{tikzpicture}
\end{center}

\noindent
After entering a procedure at $e$ and reaching node $n$,
what can we guarantee has been killed?
Only items that have been killed along \emph{both} paths!
Consequently, the kill set for $f_3$ is $K_1 \cap K_2$.
Similarly, the gen set for $f_3$ consists of items that
have been gen'd along \emph{either} path, so the
gen set for $f_3$ is $G_1 \cup G_2$.

Thus, when each gen/kill function $\lambda S.(S - K) \cup G$
is represented by a pair of sets $\B{K,G}$, we can
perform combine as follows:
\[
  \B{K_1,G_1} \combine \B{K_2,G_2} = \B{K_1 \cap K_2, G_1 \cup G_2}.
\]

\subsection{Extend}
\label{Se:Extend}

Suppose that we again have two functions
$f_1 = \lambda S.(S-K_1) \cup G_1$ and $f_2 = \lambda T.(T-K_2) \cup G_2$,
represented by the pairs of sets $\B{K_1,G_1}$ and $\B{K_2,G_2}$, respectively.
We now want to determine the appropriate function of $K_1$, $G_1$, $K_2$, and $G_2$
that should be performed to create the representation of the function
\begin{equation}
  \label{Eq:Extend}
  f_4 = \lambda S.(S-K_1) \cup G_1 \extend \lambda T.(T-K_2) \cup G_2.
\end{equation}

First, we know that extend should be compose in reverse,
so we start by writing \eqref{Extend} as a composition.
\begin{eqnarray*}
  f_4
   & = & (\lambda T.(T-K_2) \cup G_2) \circ (\lambda S.(S-K_1) \cup G_1) \\
   & = & \lambda U. (\lambda T.(T-K_2) \cup G_2) ( (\lambda S.(S-K_1) \cup G_1)(U) ) \\
   & = & \lambda U. (\lambda T.(T-K_2) \cup G_2) ((U-K_1) \cup G_1) \\
   & = & \lambda U. (((U-K_1) \cup G_1) - K_2) \cup G_2 \\ 
   & = & \lambda U. ((U-K_1)-K_2) \cup (G_1 - K_2) \cup G_2 \\
   & = & \lambda U. ((U-(K_1 \cup K_2)) \cup ((G_1 - K_2) \cup G_2) \\
\end{eqnarray*}
Consequently, when each gen/kill function $\lambda S.(S - K) \cup G$
is represented by a pair of sets $\B{K,G}$, we can
perform extend as follows:
\[
  \B{K_1,G_1} \extend \B{K_2,G_2} = \B{K_1 \cup K_2, (G_1 - K_2) \cup G_2}.
\]

\section{The Functional Approach to Interprocedural Dataflow Analysis}

The equations for $\EFAS$ given in \eqref{EFAS} are similar to
the Sharir/Pnueli equations \cite{PFA:SP81}, but only for the
intraprocedural-analysis part;
we have not yet seen the interprocedural-analysis part.

Let's consider the diagram below. 

\begin{center}
\begin{tikzpicture}
\draw [thick] (3, 0) circle [radius=.1] node [above] (e) {$e$};
\draw [thick] (5, 0) circle [radius=.1] node [above] (x) {$x$};

\draw [thick] (0,-2) circle [radius=.1] node [above] (c1) {$c_1$};
\draw [thick] (2,-2) circle [radius=.1] node [above] (r1) {$r_1$};

\draw [thick] (6,-2) circle [radius=.1] node [above] (c2) {$c_2$};
\draw [thick] (8,-2) circle [radius=.1] node [above] (r2) {$r_2$};
\draw [thick] (4,-4) circle [radius=.1] node [above] (ep) {$e'$};
\draw [thick] (6,-4) circle [radius=.1] node [above] (xp) {$x'$};

\draw [black, thick] (e) to[bend right=40] (c1);
\draw [black, thick] (r2) to[bend right=40] (x);
\draw [->, black, dashed]   (c1) to node[above] { $($} (ep);
\draw [->, black, dashed]   (xp) to node[above] { $)$} (r1);
\draw [->, orange, dashed]  (c2) to node[above] { $[$} (ep);
\draw [->, orange, dashed]  (xp) to node[above] { $]$} (r2);
\draw[decorate, decoration=snake] (c1) to node[left] {} (e);
\draw[decorate, decoration=snake] (c1) to[bend left=50] node[left] {} (r1);
\draw[decorate, decoration=snake] (r1) to[bend left=50] node[left] {} (c2);
\draw[decorate, decoration=snake] (r2) to node[left] {} (x);
\draw [->, red] plot [smooth, tension=1] coordinates { (3, 0) (0,-2) (4,-4) (6,-4) (8,-2)  };
\draw [->, black]   (ep) to[out=-145,in=-35, distance=3.5cm ]  (xp);
\end{tikzpicture}
\end{center}

\noindent
Sharir and Pnueli have the notion of $\IVP$ (which stands for ``Interprocedurally 
Valid Paths'').
One way to understand $\IVP$ is that it just involves a
filtering mechanism on paths, based on a simple context-free language.
The way to think about it is that for every call site, we introduce a pair of
matched parentheses.
In our diagram, the open parenthesis is placed on the linkage-in edge,
and the matching closed parenthesis is placed on the matching linkage-out edge.
The idea is that if we follow a call (path in red),
and we go into a called procedure via a linkage-in edge labeled ``$($,''
then we had better go back to the caller along the linkage-out edge
labeled ``$)$.''
You would never see a correctly executing procedure that follows a path
like the red path in the diagram that has a \emph{mismatched} set of parenthesis,
namely, ``$\ldots~(~\ldots~]$.''

The use of the parenthesis labels can be viewed as a policy language.
More precisely, given a language $L$ whose alphabet consists of the
labels on the edges of the graph, when we define the path problem.
We can only include the paths for which the word spelled out as
we go along the path belongs to language $L$.
A path between two nodes does not count for anything if the
path's word is not in $L$.

Going back to the declarative view of dataflow analysis that was
given in \eqref{APS}, namely,
\[
  \APS[s,n] \eqdef \bigcombine_{p \in \Paths(s,n)} \apf_p(\top),
\]
to specify the desired set of paths in the ICFG for
\emph{interprocedural} dataflow analysis, we merely
add the path-language restriction ``$p \in \unbalLeft(s,n)$''
to the index on the $\bigcombine$ operator
\[
  \APS[s,n] \eqdef \bigcombine_{p \in \unbalLeft(s,n)} \apf_p(\top).
\]

We now describe the language $\unbalLeft$ of \emph{unbalanced-left paths}.
To do so, we will need an auxiliary language of \emph{matched} paths
defined by the following context-free grammar:
\begin{eqnarray*}
    \matched   & ::= & \epsilon \\
               &  |  & \matched ~~ e \\
               &  |  & \matched ~~ (_i ~~ \matched ~~ )_i \qquad\qquad\text{for $i \in \CallSites$}
\end{eqnarray*}
We now define $\unbalLeft$ by the following grammar:\footnote{
  It is possible to write other grammars for the languages $L(\matched)$
  and $L(\unbalLeft)$.
  However, as we will see shortly, the ones given above have the advantage
  that they reflect the structure of the Sharir/Pnueli equations (and hence
  the structure of the Sharir/Pnueli algorithm for interprocedural dataflow analysis).
}
\begin{eqnarray*}
    \unbalLeft & ::= & \epsilon \\
               &  |  & \unbalLeft ~~ \matched ~~ (_i \qquad\qquad\text{for $i \in \CallSites$} \\
               &  |  & \unbalLeft ~~ \matched
\end{eqnarray*}

\section{The Sharir/Pnueli Equations in Pictures}

The three pictures that follow depict the three cases in the
Sharir/Pnueli equations.
The first two, \eqrefs{SPEqOne}{SPEqTwo}, are essentially those for
$\EFAS$;
the third handles cross-procedure propagation of dataflow information.
\begin{enumerate}
\item 
%
\begin{equation}
  \label{Eq:SPEqOne}
  \phi_{e,e} = \Id
\end{equation}
%
\begin{center}
\begin{tikzpicture}
\draw [thick] (0,0) circle [radius=.1] node [above] (e) {$e$};
\draw [thick] (2,0) circle [radius=.1] node [above] (x) {$x$};
\draw [black, thick]   (e) to[out=-145,in=-35, distance=5.5cm ] (x);
\draw [->, double, orange] (e) to[out=-145,in=-35, distance=2cm ] node[below] {$\Id$} (e);
\end{tikzpicture}
\end{center}
\item 
%
\begin{equation}
  \label{Eq:SPEqTwo}
  \phi_{e,n} = {\displaystyle \bigcombine_{\B{m,n} \in \Edges}} f_{m,n} \circ \phi_{e,m} \text{ if } n \notin \Ret
\end{equation}
Alternatively, \eqref{SPEqTwo} can be stated in terms of extend:
\begin{equation}
  \label{Eq:SPEqTwoAlternative}
  \phi_{e,n} = {\displaystyle \bigcombine_{\B{m,n} \in \Edges}} \phi_{e,m} \extend f_{m,n} \text{ if } n \notin \Ret
\end{equation}

%
\begin{center}
\begin{tikzpicture}
\draw [thick] (0,0) circle [radius=.1] node [above] (e) {$e$};
\draw [thick] (2,0) circle [radius=.1] node [above] (x) {$x$};
\draw [black, thick]   (e) to[out=-145,in=-35, distance=8.5cm ] (x);
\draw [thick] (1.5,-2) circle [radius=.05] node [above] (m1) {$m_1$};
\draw [thick] (0,-3) circle [radius=.05] node [above] (mk) {$m_k$};
\draw [thick] (2,-3) circle [radius=.05] node [above] (n) {$n$};
\draw[->, double] (e) to[bend right=60] (mk);
\draw[->, double] (e) to[bend right=60] (m1);
\draw[->] (mk) to (n);
\draw[->] (m1) to (n);
\draw[->, double, orange] (e) to[bend left] node[right] {} (n);
\end{tikzpicture}
\end{center}
\item
The third case handles cross-procedure propagation of \emph{summary functions}
of the form $\phi_{e',x'}$.
Note that such a $\phi$ function summarizes the net effect of all
matched-parenthesis paths from entry node $e'$ to exit node $x'$.
%
Sharir and Pnueli give an equation that---when re-expressed to use
extend rather than function composition---looks like
\begin{equation}
  \label{Eq:SPEqThree}
  \phi_{e,r} = \phi_{e,c} \extend \phi_{e',x'}.
\end{equation}
\eqref{SPEqThree} looks a bit odd because Sharir and Pnueli make the
assumption that the action on every linkage-in edge and
every linkage-out edge is $\Id$.
Thus, when accompanied by the diagram below,
the equation might be more clearly expressed with two
redundant occurrences of $\Id$.
\begin{equation}
  \label{Eq:SPEqThreeAlternative}
  \phi_{e,r} = \phi_{e,c} \extend \Id \extend \phi_{e',x'} \extend \Id,
\end{equation}
%
\begin{center}
\begin{tikzpicture}
\draw [thick] (0,0) circle [radius=.1] node [above] (e) {$e$};
\draw [thick] (3,0) circle [radius=.1] node [above] (x) {$x$};
\draw [thick] (0,-3) circle [radius=.1] node [above] (c) {$c$};
\draw [thick] (3,-3) circle [radius=.1] node [above] (r) {$r$};
\draw [thick] (0,-5) circle [radius=.1] node [above] (ep) {$e'$};
\draw [thick] (3,-5) circle [radius=.1] node [above] (xp) {$x'$};
\draw [black, thick]        (e) to[bend right=70] (c);
\draw [->, double]          (e) to[bend right=3] node[left] {$\phi_{e,c}$} (c);
\draw [->, double, dashed]  (e) to[bend left=0]  (r);
\draw [black,thick]         (r) to[bend right=70]  (x);
\draw [->, dashed]          (c) to node[left] {$\Id$}  (ep);
\draw [->, double]          (ep) to[bend right=3]  node[above] { $\phi_{e',x'}$} (xp);
\draw [black, thick]   (ep) to[out=-145,in=-35, distance=5.5cm ] (xp);
\draw [->, dashed]          (xp) to node[right] { $\Id$ } (r);
\end{tikzpicture}
\end{center}
%
To allow the actions on linkage-in and linkage-out edges to be other than
$\Id$, we would use the following equation:
\begin{equation}
  \label{Eq:SPEqThreeAlternativeGeneralized}
  \phi_{e,r} = \phi_{e,c} \extend \CallIn_{c,e'} \extend \phi_{e',x'} \extend \CallOut_{x', r}.
\end{equation}
\end{enumerate}

It is instructive to go back to the grammar for the language
$L(\matched)$ of matched parentheses and see how the structure of
\eqrefsp{SPEqOne}{SPEqTwoAlternative}{SPEqThreeAlternativeGeneralized}
matches the structure of the different grammar rules exactly
\[
\begin{array}{@{\hspace{0ex}}r@{\hspace{1ex}}c@{\hspace{1ex}}l@{\hspace{5ex}}l@{\hspace{0ex}}}
    \matched   & ::= & \epsilon            & (\textrm{cf.\ \eqref{SPEqOne}}) \\
               &  |  & \matched ~~ e       & (\textrm{cf.\ \eqref{SPEqTwoAlternative}}) \\
               &  |  & \matched ~~ (_i ~~ \matched ~~ )_i & (\textrm{cf.\ \eqref{SPEqThreeAlternativeGeneralized}})
\end{array}
\]

\paragraph{Supporting Local Variables.}
Although we will not cover it here, for an analysis that tracks
information about local variables, and for a programming language
that supports recursion, the action on the linkage-in edge
is to forget information about caller locals, and at the
exit node a two-argument \emph{merge function} \cite{CC:KS92}
is applied that uses
(i) information from $\phi_{e',x'}$ to forget information about callee locals
and (ii) information from $\phi_{e,c}$ to restore information about caller locals.
%
\begin{center}
\begin{tikzpicture}
\draw [thick] (0,0) circle [radius=.1] node [above] (e) {$e$};
\draw [thick] (3,0) circle [radius=.1] node [above] (x) {$x$};
\draw [thick] (0,-3) circle [radius=.1] node [above] (c) {$c$};
\draw [thick] (3,-3) circle [radius=.1] node [above] (r) {$r$};
\draw [thick] (0,-5) circle [radius=.1] node [above] (ep) {$e'$};
\draw [thick] (3,-5) circle [radius=.1] node [above] (xp) {$x'$};
\draw [thick] (2.5,-3.7) circle [radius=.24] node  (M) {$M$};
\draw [black, thick]        (e) to[bend right=70] (c);
\draw [->, double]          (e) to[bend right=3] node[left] {$\phi_{e,c}$} (c);
\draw [->, double, dashed]  (e) to[bend left=0]  (r);
\draw [black, thick]        (r) to[bend right=70]  (x);
\draw [->, dashed]          (c) to node[left] {\tiny{Forget caller locals}}  (ep);
\draw [->, double]          (ep) to[bend right=3]  node[above] { $\phi_{e',x'}$} (xp);
\draw [black, thick]   (ep) to[out=-145,in=-35, distance=5.5cm ] (xp);
\draw [->, dashed]          (c) to[bend right=7] node[above] {\tiny{Restore caller}} node[below] {\tiny{locals}} (M);
\draw [->, dashed]          (xp) to[bend left=7] node[right]{\tiny{Forget callee locals}} (M);
\draw [->, dashed]          (M) to (r);
\end{tikzpicture}
\end{center}
The equation that would be used in place of \eqref{SPEqThree} (or
\eqref{SPEqThreeAlternativeGeneralized}) is as follows:
\begin{eqnarray*}
  \phi_{e,r} & = & M(\phi_{e,c},\phi_{e',x'}).
\end{eqnarray*}
Other work that uses merge functions includes \cite{POPL:MOS04,CAV:LRB05}.
The idea of ``peeking back at the call-site'' has been imported into
automata theory in the work on visibly pushdown automata
\cite{STOC:AM04} and nested-word automata \cite{DLT:AM2006}.

{\small
  \bibliography{cs701}
  \bibliographystyle{plain}
}
 
\end{document}