CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
144 lines
6.2 KiB
TeX
144 lines
6.2 KiB
TeX
\subsection{Expression Class}
|
|
\label{sec:expression}
|
|
|
|
An \code{Expression} is an AST representation of how the value of an operand is
|
|
computed.
|
|
|
|
The \code{Expression} class extends the \code{InstructionAST} class by adding the concept of
|
|
evaluation to the nodes of an \code{InstructionAST}. Evaluation attempts to determine
|
|
the \code{Result} of the
|
|
computation that the AST being evaluated represents. It will fill in results of
|
|
as many of the nodes in the tree as possible, and if full evaluation is
|
|
possible, it will return the result of the computation performed by the tree.
|
|
|
|
Permissible leaf nodes of an \code{Expression} tree are RegisterAST and Immediate
|
|
objects. Permissible internal nodes are \code{BinaryFunction} and Dereference objects.
|
|
An \code{Expression} may represent an immediate value, the contents of a register, or
|
|
the contents of memory at a given address, interpreted as a particular type.
|
|
|
|
The \code{Result}s in an \code{Expression} tree contain a type and a value. Their values may
|
|
be an undefined value or an instance of their associated type. When two \code{Result}s
|
|
are combined using a \code{BinaryFunction}, the \code{BinaryFunction} specifies the output
|
|
type. Sign extension, type promotion, truncation, and all other necessary
|
|
conversions are handled automatically based on the input types and the output
|
|
type. If both of the \code{Result}s that are combined have defined values, the
|
|
combination will also have a defined value; otherwise, the combination's value
|
|
will be undefined. For more information, see
|
|
Section~\ref{sec:result}, Section~\ref{sec:binaryFunction}, and
|
|
Section~\ref{sec:dereference}.
|
|
|
|
A user may specify the result of evaluating a given \code{Expression}. This mechanism
|
|
is designed to allow the user to provide a Dereference or RegisterAST with
|
|
information about the state of memory or registers. It may additionally be used
|
|
to change the value of an Immediate or to specify the result of a
|
|
\code{BinaryFunction}. This mechanism may be used to support other advanced analyses.
|
|
|
|
In order to make it more convenient to specify the results of particular
|
|
subexpressions, the \code{bind} method is provided. \code{bind} allows the user
|
|
to specify that a given subexpression has a particular value everywhere that it
|
|
appears in an expression. For example, if the state of certain registers is
|
|
known at the time an instruction is executed, a user can \code{bind} those
|
|
registers to their known values throughout an \code{Expression}.
|
|
|
|
The evaluation mechanism, as mentioned above, will evaluate as many
|
|
sub-\/expressions of an expression as possible. Any operand that is more
|
|
complicated than a single immediate value, however, will depend on register or
|
|
memory values. The \code{Result}s of evaluating each subexpression are cached
|
|
automatically using the \code{setValue} mechanism. The \code{Expression} then attempts
|
|
to determine its \code{Result} based on the \code{Result}s of its children. If this \code{Result} can
|
|
be determined (most likely because register contents have been filled in via
|
|
\code{setValue} or \code{bind}), it will be returned from \code{eval}; if it can
|
|
not be determined, a \code{Result} with an undefined value will be returned. See Figure
|
|
6 for an illustration of this concept; the operand represented is
|
|
\code{[ \code{EBX} + \code{4} $\ast$ \code{EAX} ]}.
|
|
The contents of \code{EBX} and \code{EAX} have been determined through some
|
|
outside mechanism, and have been defined with \code{setValue}. The \code{eval}
|
|
mechanism proceeds to determine the address being read by the \code{Dereference}, since
|
|
this information can be determined given the contents of the registers. This
|
|
address is available from the Dereference through its child in the tree, even
|
|
though calling \code{eval} on the Dereference returns a \code{Result} with an
|
|
undefined value.
|
|
|
|
\begin{figure}
|
|
\centering
|
|
\includegraphics{fig/deref-eval}
|
|
\caption{Applying \code{eval} to a Dereference tree with two registers
|
|
having user-provided values.}
|
|
\label{fig:deref-eval}
|
|
\end{figure}
|
|
|
|
\begin{apient}
|
|
typedef boost::shared_ptr<Expression> Ptr
|
|
\end{apient}
|
|
\apidesc{
|
|
A type definition for a reference-counted pointer to an \code{Expression}.
|
|
}
|
|
|
|
\begin{apient}
|
|
const Result & eval() const
|
|
\end{apient}
|
|
\apidesc{
|
|
If the \code{Expression} can be evaluated, returns a \code{Result}
|
|
containing its value. Otherwise returns an undefined \code{Result}.
|
|
}
|
|
|
|
\begin{apient}
|
|
const setValue(const Result & knownValue)
|
|
\end{apient}
|
|
\apidesc{
|
|
Sets the result of \code{eval} for this \code{Expression} to
|
|
\code{knownValue}.
|
|
}
|
|
|
|
\begin{apient}
|
|
void clearValue()
|
|
\end{apient}
|
|
\apidesc{
|
|
\code{clearValue} sets the contents of this \code{Expression} to undefined.
|
|
The next time \code{eval} is called, it will recalculate the value of the
|
|
\code{Expression}.
|
|
}
|
|
|
|
\begin{apient}
|
|
int size() const
|
|
\end{apient}
|
|
\apidesc{
|
|
\code{size} returns the size of this \code{Expression}'s \code{Result}, in
|
|
bytes.
|
|
}
|
|
|
|
\begin{apient}
|
|
bool bind(Expression * expr, const Result & value)
|
|
\end{apient}
|
|
\apidesc{
|
|
\code{bind} searches for all instances of the Expression \code{expr} within
|
|
this Expression, and sets the result of \code{eval} for those subexpressions
|
|
to \code{value}. \code{bind} returns \code{true} if at least one instance of
|
|
\code{expr} was found in this Expression.
|
|
|
|
\code{bind} does not operate on subexpressions that happen to evaluate to
|
|
the same value. For example, if a dereference of \code{0xDEADBEEF} is bound
|
|
to 0, and a register is bound to \code{0xDEADBEEF}, a deference of that
|
|
register is not bound to 0.
|
|
}
|
|
|
|
\begin{apient}
|
|
virtual void apply(Visitor *)
|
|
\end{apient}
|
|
\apidesc{
|
|
\code{apply} applies a \code{Visitor} to this \code{Expression}. Visitors
|
|
perform postfix-order traversal of the ASTs represented by an
|
|
\code{Expression}, with user-defined actions performed at each node of the
|
|
tree. We present a thorough discussion with examples in Section
|
|
\ref{sec:visitor}.
|
|
}
|
|
|
|
\begin{apient}
|
|
virtual void getChildren(std::vector<Expression::Ptr> & children) const
|
|
\end{apient}
|
|
\apidesc{
|
|
\code{getChildren} may be called on an \code{Expression} taking a vector of
|
|
\code{ExpressionPtr}s, rather than \code{InstructionAST}Ptrs. All children
|
|
which are \code{Expression}s will be appended to \code{children}.
|
|
}
|