Go to the previous, next section.

A Simple Example of What the Builder Can Do

This is a complete example of a SUIF pass that will modify programs.

Assume that this pass must add a special local variable to each procedure in the input program. This variable needs to hold a special value while the procedure is active. The lower 6 bits of this value should hold an unique identifier number of the procedure, the next 9 bits hold the initial value of the first parameter and the highest bit should be one. If any of those numbers overflow, the value should be zero. Note that overflowing of the unique identifier can be calculated at compile time but the first parameter needs to be checked at runtime. Assume each procedure has at least one parameter and that the first parameter is an integer.

main.cc

#include <stdlib.h>
#include <suif.h>
#include <builder.h>

int UID;

void do_proc(tree_proc * tp)
{
    block::set_proc(tp);

    sym_node_list * snl = tp->proc_syms()->params();
    assert(snl->count() > 0);
    assert((*snl)[0]->is_var());
    var_sym * first_param = (var_sym *)(*snl)[0];

    block fp_var(first_param);

    type_node * type = block::parse_type("int32");

    block num_var(block::new_sym(type, "proc_id")); 
     
    block setid;
    if(UID <= 0x3F) {
        block count(UID);

        setid.set(block::IF((fp_var <= block(0x1FF)),
                            (num_var = block(0x8000) + 
                                       fp_var << block(6) + 
                                       count),
                            (num_var = 0x0000)));
    } else
        setid.set(num_var = block(0x0000));

    tree_node * tn = setid.make_tree_node();

    tp->body()->push(tn);

    UID++;   
}

main(int argc, char * argv[])
{
    start_suif(argc, argv);
    UID = 0;
    suif_proc_iter(argc, argv, do_proc, TRUE, TRUE, TRUE);
}

The above C++ program is a SUIF pass that will accomplish this task. For all the procedures in the input program, the call to `do_proc' will incorporate the above mentioned local variable to the SUIF procedure. The following steps are carried-out by `do_proc'.

  1. The SUIF procedure `tp' is initialized as the current procedure for the builder to modify. The set_proc function should be called before any use of builder functions.

  2. The variable symbol of the first parameter (`first_param') is found.

  3. The block `fp_var' holds the variable `first_param'.

  4. The type node for integer type is created.

  5. A new local integer variable named `proc_id' is created. The block `num_var' holds this variable.

  6. Check if the unique number `UID' is within bounds.

  7. The block `count' holds the integer representing the unique number for the current SUIF procedure.

  8. The block `setid' is assigned a structure that will create the neccessary SUIF code needed to initialize the variable. The IF conditional will create a runtime check of the parameter. If it is within bounds, the `num_var' will be set to the correct value. Otherwise, `num_var' is set to zero at runtime.

  9. It can be known at compile-time if `UID' exceeds its range. If so, `num_var' is set to zero at runtime.

  10. Actually generate the SUIF code.

  11. Insert the SUIF code that the beginning of the current SUIF procedure.

  12. Increment the `UID'.

Makefile

Here is the Makefile for the above pass.

TARGET =	ex
LIBS =		-lbuilder -lsuif -luseful -lm
SRCS =		main.cc
OBJS =		main.o 
all:		ex
install-bin:	install-prog
include $(SUIFHOME)/Makefile.std

Building the Compiler Pass

csh> gmake
g++ -c -g -Wall  -I/hawg/suif/hawg/include   main.cc
g++ -c -g -Wall  -I/hawg/suif/hawg/include   suif_init.cc
g++ -o ex -g -Wall  -I/hawg/suif/hawg/include   main.o  suif_init.o \
                 -L/hawg/suif/hawg/MIPSEL/lib  \
                 -lbuilder -lsuif -luseful -lm prog_ver.cc

Testing the Compiler Pass

The SUIF pass can be tested by applying it to a few input programs. First, the input file is compiled down to SUIF. Then the pass that was created is applied to the input SUIF file and a resulting SUIF file is generated. Finally, the resulting SUIF file is converted back to C.

The Input File test.c

t0(int i)  {    }
t2(int k)  {    }
t3(int l)  {    }
...
t15(int j) {    }
...
t63(int y) {    }
t64(int x) {    }
t65(int z) {    }

Test Session

csh> scc -.sf- test.c
csh> ex test.sf- test.sfx
csh> s2c test.sfx > test.sfx.c

The Output File test.sfx.c

extern int t0(int i)
{
    unsigned short proc_id0;
    if (i <= 511) 
        proc_id0 = 32768 + i << 6 + 0;
    else 
        proc_id0 = 0;
    return 0;
}
...
extern int t15(int j)
{
    unsigned short proc_id0;
    if (j <= 511)
        proc_id0 = 32768 + j << 6 + 15;
    else 
        proc_id0 = 0;
    return 0;
}
...
extern int t64(int x)
{
    unsigned short proc_id0;
    proc_id0 = 0;
    return 0;
}

Go to the previous, next section.