Register allocation is a complex and error prone activity. One of the problems in writing register allocation algorithms is how to verify if the code being generated is correct. In this page you can find a tool that automatically verifies if register allocation directives written according to RALF's specification are correct. In order to perform this verification, the debugger checks the target allocation directives against five rules. It is possible to prove that if all the rules are satisfied then the allocation is correct.
RALF is a framework that allows to test different register allocation algorithms. It provides the application developer with a program description format called MIRA. It compiles C programs, and generated a MIRA description for them. The application developer can use the MIRA description to determine how registers should be allocated. With such specifications in hands, he must generated a allocation description in the FORD format. RALF will generate C binaries from the FORD file. Such binaries can be executed in an ARM processor. For further description of RALF, check here. An schmematic description of the RALF architecture is given in the Figure below.
C
procedure, and automatically checks their consistency
according to the set of rules that it defines. A schematic view of the
automatic verification process can be seen in the Figure below.
The debugger does not check the syntax of the register allocation directives, because this is already done by Ralf's parser. Syntactic errors include incorrect input files, due to incompatibility with Ford or Mira's grammar, and also the incorrect spelling of the allocation directives. Other, not so trivial syntax errors, include the use of non-existent machine registers, non-existent instructions, or non-existent temporaries.
The sources that can be downloaded in this page contain the implementation
of four register allocation algorithms. You can use such algorithms as a
starting point for a different implementation, and also to get familiarized
with the debugging tools.
The package RegAlloc
contains the implementation of the following
register allocators:
RegAlloc
: this package contains basic data
structures such as the interfaces for registers, instructions
and register allocators.
RegAlloc.Naive
: this package contains the implementation
of the naive register allocator.
RegAlloc.IRC
: this package contains the implementation
of iterated register coalescing.
RegAlloc.ChordalAllocation
: this package contains the
implementation of register allocation via coloring of chordal graphs.
RegAlloc.RalfTools
: this package contains some useful
tools to deal with MIRA/FORD files. The debugger and the MIRA/FORD visualizer
are in this package. Also, this package contains programs to draw the
interference graph, to compute liveness analysis, etc. .
RegAlloc.KrParser
: this package contains a parser that
generates an intance of the register allocation problem from a MIRA
specification, and outputs the resulting FORD file given the
results of the register allocation process.
RegAlloc.SSA
: this package contains algorithms to
converting a control flow graph to the SSA form. The package contains
implementations of algorithms to build the dominance tree of a CFG, to find
the dominance frontier of each node, to insert phi functions into the CFG,
and to rename variables, after phi functions have been placed.
Graph
: this package contains the implementation of a
undirected graph library. It is used to represent the interference graphs.
Digraph
: this package contains the implementation of a
directed graph library. It is used to represent the control flow graph
of programs.
utilities
: this package contains the implementation of
some useful data structures that carry on operations on lists, such as
intersection, sorting, etc.
In addition to the Java source files, the following scripts are available:
debug
: This script calls the debugger.
cfd
: This script calls the MIRA visualizer.
solve_constraints
: This script determines which
register allocator will be used.
comp
: This script compiles a C program using the
register allocator defined in solve_constraints
.
fcc
: This script defines the compilation directives that
bind the register allocators to Ralf.
fld
: This script determines the linker that will be
used after the C programs have been compiled.
It is easier to find errors in register assignment directives if you can inspect the control flow graph. To make this possible, the debugging framework makes available a program that generates the representation of the control flow graph in .dot format. The (.dot) format can be visualized using some free tools such as Graphviz.
There are two ways to run the mira visualizer. If you are interested in
visualizing only the control flow graph, and are not taking into consideration
how are the registes allocated to temporaries, you just need the (.dat)
file containing MIRA directives. In this case, in order to run the MIRA
visualizer, type java RegAlloc.ControlFlowViewer
file.dat
. Below there is an example of .c source file, and the corresponding
.dot
file as opened with Omnigrafle (a shareware version of
Omnigrafle can be downloaded
here).
The graph contains orange and blue nodes. Blue nodes denote function calls.
It is important to know which instructions are function calls, because the
register allocator must make sure that the caller save registers are not alive
accross function calls.
The control flow graph above has been generated from the source file below. The corresponding .dat file can be downloaded here.
int main(int argc, char **argv) { int sum = 0; int counter = 0; for(counter = 1; counter < argc; counter++) { char *aux = argv[counter]; while(*aux != '\0') { aux++; sum++; } } printf("Sum = %d\n", sum); }If you want to check how registers have been assigned to temporary variables, you will need both, the MIRA description (file.dat), and the FORD directives (file.out). In this case, type
java
RegAlloc.ControlFlowViewer file.dat file.out
. The figure below shows
the register allocation
produced by the Iterated Register Coalescer algorithm for the program used in
the previous example. Each temporary appears in the format t(r)
,
where t
is the temporary's name, and r
is the
machine register's name.
debug mira.dat ford.out
. The debugger will report inconsistencies
in the allocation directives according to the five following rules:
The debugger can print the error messages enumerated below. A detailed description of each error can be found here.
Última atualização:
18 de Abril 2006.