For PR1074:
[oota-llvm.git] / projects / Stacker / lib / compiler / StackerCompiler.cpp
diff --git a/projects/Stacker/lib/compiler/StackerCompiler.cpp b/projects/Stacker/lib/compiler/StackerCompiler.cpp
deleted file mode 100644 (file)
index 1542645..0000000
+++ /dev/null
@@ -1,1806 +0,0 @@
-//===-- StackerCompiler.cpp - Parser for llvm assembly files ----*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file was developed by Reid Spencer and donated to the LLVM research
-// group and is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements the compiler for the "Stacker" language.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "stacker"
-#include "llvm/PassManager.h"
-#include "llvm/Analysis/LoadValueNumbering.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/Parser.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Instructions.h"
-#include "llvm/ADT/Statistic.h"
-#include "StackerCompiler.h"
-#include "StackerParser.h"
-#include <string>
-
-// Lexer/Parser defined variables and functions
-extern std::FILE *Stackerin;
-extern int Stackerlineno;
-extern char* Stackertext;
-extern int Stackerleng;
-extern int Stackerparse();
-
-StackerCompiler* StackerCompiler::TheInstance = 0;
-
-STATISTIC(NumDefinitions, "The number of definitions encountered");
-
-StackerCompiler::StackerCompiler()
-    : CurFilename("")
-    , TheModule(0)
-    , TheFunction(0)
-    , DefinitionType(0)
-    , TheStack(0)
-    , TheIndex(0)
-    , TheScanf(0)
-    , ThePrintf(0)
-    , TheExit(0)
-    , StrFormat(0)
-    , NumFormat(0)
-    , ChrFormat(0)
-    , InStrFormat(0)
-    , InNumFormat(0)
-    , InChrFormat(0)
-    , Zero(0)
-    , One(0)
-    , Two(0)
-    , Three(0)
-    , Four(0)
-    , Five(0)
-    , no_arguments()
-    , echo(false)
-    , stack_size(256)
-    , stack_type(0)
-{
-}
-
-StackerCompiler::~StackerCompiler()
-{
-    // delete TheModule; << don't do this!
-    // TheModule is passed to caller of the compile() method .. its their
-    // problem.  Likewise for the other allocated objects (which become part
-    // of TheModule.
-    TheModule = 0;
-    DefinitionType = 0;
-    TheStack = 0;
-    TheIndex = 0;
-}
-
-Module*
-StackerCompiler::compile(
-    const std::string& filename,
-    bool should_echo,
-    unsigned optLevel,
-    size_t the_stack_size
-)
-{
-    // TODO: Provide a global lock to protect the singled-threaded compiler
-    // and its global variables. Should be in guard object on the stack so
-    // that its destructor causes lock to be released (multiple exits from
-    // this function).
-
-    // Assign parameters
-    CurFilename = filename;
-    echo = should_echo;
-    stack_size = the_stack_size;
-
-    /// Default the file to read
-    FILE *F = stdin;
-
-    ///
-    if (filename != "-")
-    {
-        F = fopen(filename.c_str(), "r");
-
-        if (F == 0)
-        {
-          ParseError Err;
-          Err.setError(filename, "Could not open file '" + filename + "'");
-          throw Err;
-        }
-    }
-
-    try
-    {
-        // Create the module we'll return
-        TheModule = new Module( CurFilename );
-
-        // Tell the module about our runtime library
-        TheModule->addLibrary("stkr_runtime");
-
-        // Create a type to represent the stack. This is the same as the LLVM
-        // Assembly type [ 256 x long ]
-        stack_type = ArrayType::get( Type::Int64Ty, stack_size );
-
-        // Create a global variable for the stack. Note the use of appending
-        // linkage linkage so that multiple modules will make the stack larger.
-        // Also note that the last argument causes the global to be inserted
-        // automatically into the module.
-        TheStack = new GlobalVariable(
-            /*type=*/ stack_type,
-            /*isConstant=*/ false,
-            /*Linkage=*/ GlobalValue::LinkOnceLinkage,
-            /*initializer=*/ Constant::getNullValue(stack_type),
-            /*name=*/ "_stack_",
-            /*parent=*/ TheModule
-        );
-
-        // Create a global variable for indexing into the stack. Note the use
-        // of LinkOnce linkage. Only one copy of _index_ will be retained
-        // after linking
-        TheIndex = new GlobalVariable(
-            /*type=*/Type::Int64Ty,
-            /*isConstant=*/false,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/ Constant::getNullValue(Type::Int64Ty),
-            /*name=*/"_index_",
-            /*parent=*/TheModule
-        );
-
-        // Create a function prototype for definitions. No parameters, no
-        // result.  This is used below any time a function is created.
-        std::vector<const Type*> params; // No parameters
-        DefinitionType = FunctionType::get( Type::VoidTy, params, false );
-
-        // Create a function for printf(3)
-        params.push_back( PointerType::get( Type::Int8Ty ) );
-        FunctionType* printf_type =
-            FunctionType::get( Type::Int32Ty, params, true );
-        ThePrintf = new Function(
-            printf_type, GlobalValue::ExternalLinkage, "printf", TheModule);
-
-        // Create a function for scanf(3)
-        TheScanf = new Function(
-            printf_type, GlobalValue::ExternalLinkage, "scanf", TheModule);
-
-        // Create a function for exit(3)
-        params.clear();
-        params.push_back( Type::Int32Ty );
-        FunctionType* exit_type =
-            FunctionType::get( Type::VoidTy, params, false );
-        TheExit = new Function(
-            exit_type, GlobalValue::ExternalLinkage, "exit", TheModule);
-
-        Constant* str_format = ConstantArray::get("%s");
-        StrFormat = new GlobalVariable(
-            /*type=*/ArrayType::get( Type::Int8Ty,  3 ),
-            /*isConstant=*/true,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/str_format,
-            /*name=*/"_str_format_",
-            /*parent=*/TheModule
-        );
-
-        Constant* in_str_format = ConstantArray::get(" %as");
-        InStrFormat = new GlobalVariable(
-            /*type=*/ArrayType::get( Type::Int8Ty,  5 ),
-            /*isConstant=*/true,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/in_str_format,
-            /*name=*/"_in_str_format_",
-            /*parent=*/TheModule
-        );
-
-        Constant* num_format = ConstantArray::get("%d");
-        NumFormat = new GlobalVariable(
-            /*type=*/ArrayType::get( Type::Int8Ty,  3 ),
-            /*isConstant=*/true,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/num_format,
-            /*name=*/"_num_format_",
-            /*parent=*/TheModule
-        );
-
-        Constant* in_num_format = ConstantArray::get(" %d");
-        InNumFormat = new GlobalVariable(
-            /*type=*/ArrayType::get( Type::Int8Ty,  4 ),
-            /*isConstant=*/true,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/in_num_format,
-            /*name=*/"_in_num_format_",
-            /*parent=*/TheModule
-        );
-
-        Constant* chr_format = ConstantArray::get("%c");
-        ChrFormat = new GlobalVariable(
-            /*type=*/ArrayType::get( Type::Int8Ty,  3 ),
-            /*isConstant=*/true,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/chr_format,
-            /*name=*/"_chr_format_",
-            /*parent=*/TheModule
-        );
-
-        Constant* in_chr_format = ConstantArray::get(" %c");
-        InChrFormat = new GlobalVariable(
-            /*type=*/ArrayType::get( Type::Int8Ty,  4 ),
-            /*isConstant=*/true,
-            /*Linkage=*/GlobalValue::LinkOnceLinkage,
-            /*initializer=*/in_chr_format,
-            /*name=*/"_in_chr_format_",
-            /*parent=*/TheModule
-        );
-
-        // Get some constants so we aren't always creating them
-        Zero = ConstantInt::get( Type::Int64Ty, 0 );
-        One = ConstantInt::get( Type::Int64Ty, 1 );
-        Two = ConstantInt::get( Type::Int64Ty, 2 );
-        Three = ConstantInt::get( Type::Int64Ty, 3 );
-        Four = ConstantInt::get( Type::Int64Ty, 4 );
-        Five = ConstantInt::get( Type::Int64Ty, 5 );
-
-        // Reset the current line number
-        Stackerlineno = 1;
-
-        // Reset the parser's input to F
-        Stackerin = F;          // Set the input file.
-
-        // Let the parse know about this instance
-        TheInstance = this;
-
-        // Parse the file. The parser (see StackParser.y) will call back to
-        // the StackerCompiler via the "handle*" methods
-        Stackerparse();
-
-        // Avoid potential illegal use (TheInstance might be on the stack)
-        TheInstance = 0;
-
-        // Set up a pass manager
-        PassManager Passes;
-        // Add in the passes we want to execute
-        Passes.add(new TargetData(TheModule));
-        // Verify we start with valid
-        Passes.add(createVerifierPass());
-
-        if (optLevel > 0) {
-            if (optLevel > 1) {
-                // Clean up disgusting code
-                Passes.add(createCFGSimplificationPass());
-                // Remove unused globals
-                Passes.add(createGlobalDCEPass());
-                // IP Constant Propagation
-                Passes.add(createIPConstantPropagationPass());
-                // Clean up after IPCP
-                Passes.add(createInstructionCombiningPass());
-                // Clean up after IPCP
-                Passes.add(createCFGSimplificationPass());
-                // Inline small definitions (functions)
-                Passes.add(createFunctionInliningPass());
-                // Simplify cfg by copying code
-                Passes.add(createTailDuplicationPass());
-                if (optLevel > 2) {
-                    // Merge & remove BBs
-                    Passes.add(createCFGSimplificationPass());
-                    // Compile silly sequences
-                    Passes.add(createInstructionCombiningPass());
-                    // Reassociate expressions
-                    Passes.add(createReassociatePass());
-                    // Combine silly seq's
-                    Passes.add(createInstructionCombiningPass());
-                    // Eliminate tail calls
-                    Passes.add(createTailCallEliminationPass());
-                    // Merge & remove BBs
-                    Passes.add(createCFGSimplificationPass());
-                    // Hoist loop invariants
-                    Passes.add(createLICMPass());
-                    // Clean up after the unroller
-                    Passes.add(createInstructionCombiningPass());
-                    // Canonicalize indvars
-                    Passes.add(createIndVarSimplifyPass());
-                    // Unroll small loops
-                    Passes.add(createLoopUnrollPass());
-                    // Clean up after the unroller
-                    Passes.add(createInstructionCombiningPass());
-                    // GVN for load instructions
-                    Passes.add(createLoadValueNumberingPass());
-                    // Remove common subexprs
-                    Passes.add(createGCSEPass());
-                    // Constant prop with SCCP
-                    Passes.add(createSCCPPass());
-                }
-                if (optLevel > 3) {
-                    // Run instcombine again after redundancy elimination
-                    Passes.add(createInstructionCombiningPass());
-                    // Delete dead stores
-                    Passes.add(createDeadStoreEliminationPass());
-                    // SSA based 'Aggressive DCE'
-                    Passes.add(createAggressiveDCEPass());
-                    // Merge & remove BBs
-                    Passes.add(createCFGSimplificationPass());
-                    // Merge dup global constants
-                    Passes.add(createConstantMergePass());
-                }
-            }
-
-            // Merge & remove BBs
-            Passes.add(createCFGSimplificationPass());
-            // Memory To Register
-            Passes.add(createPromoteMemoryToRegisterPass());
-            // Compile silly sequences
-            Passes.add(createInstructionCombiningPass());
-            // Make sure everything is still good.
-            Passes.add(createVerifierPass());
-        }
-
-        // Run our queue of passes all at once now, efficiently.
-        Passes.run(*TheModule);
-
-    } catch (...) {
-        if (F != stdin) fclose(F);      // Make sure to close file descriptor
-        throw;                          // if an exception is thrown
-    }
-
-    // Close the file
-    if (F != stdin) fclose(F);
-
-    // Return the compiled module to the caller
-    return TheModule;
-}
-
-//===----------------------------------------------------------------------===//
-//            Internal Functions, used by handleXXX below.
-//            These represent the basic stack operations.
-//===----------------------------------------------------------------------===//
-
-Instruction*
-StackerCompiler::incr_stack_index( BasicBlock* bb, Value* ival = 0 )
-{
-    // Load the value from the TheIndex
-    LoadInst* loadop = new LoadInst( TheIndex );
-    bb->getInstList().push_back( loadop );
-
-    // Increment the loaded index value
-    if ( ival == 0 ) ival = One;
-    CastInst* caster = CastInst::createSExtOrBitCast( ival, Type::Int64Ty );
-    bb->getInstList().push_back( caster );
-    BinaryOperator* addop = BinaryOperator::create( Instruction::Add,
-            loadop, caster);
-    bb->getInstList().push_back( addop );
-
-    // Store the incremented value
-    StoreInst* storeop = new StoreInst( addop, TheIndex );
-    bb->getInstList().push_back( storeop );
-    return storeop;
-}
-
-Instruction*
-StackerCompiler::decr_stack_index( BasicBlock* bb, Value* ival = 0 )
-{
-    // Load the value from the TheIndex
-    LoadInst* loadop = new LoadInst( TheIndex );
-    bb->getInstList().push_back( loadop );
-
-    // Decrement the loaded index value
-    if ( ival == 0 ) ival = One;
-    CastInst* caster = CastInst::createSExtOrBitCast( ival, Type::Int64Ty );
-    bb->getInstList().push_back( caster );
-    BinaryOperator* subop = BinaryOperator::create( Instruction::Sub,
-            loadop, caster);
-    bb->getInstList().push_back( subop );
-
-    // Store the incremented value
-    StoreInst* storeop = new StoreInst( subop, TheIndex );
-    bb->getInstList().push_back( storeop );
-
-    return storeop;
-}
-
-Instruction*
-StackerCompiler::get_stack_pointer( BasicBlock* bb, Value* index = 0 )
-{
-    // Load the value of the Stack Index
-    LoadInst* loadop = new LoadInst( TheIndex );
-    bb->getInstList().push_back( loadop );
-
-    // Index into the stack to get its address. NOTE the use of two
-    // elements in this vector. The first de-references the pointer that
-    // "TheStack" represents. The second indexes into the pointed to array.
-    // Think of the first index as getting the address of the 0th element
-    // of the array.
-    std::vector<Value*> indexVec;
-    indexVec.push_back( Zero );
-
-    if ( index == 0 )
-    {
-        indexVec.push_back(loadop);
-    }
-    else
-    {
-        CastInst* caster = CastInst::createSExtOrBitCast( index, Type::Int64Ty );
-        bb->getInstList().push_back( caster );
-        BinaryOperator* subop = BinaryOperator::create(
-            Instruction::Sub, loadop, caster );
-        bb->getInstList().push_back( subop );
-        indexVec.push_back(subop);
-    }
-
-    // Get the address of the indexed stack element
-    GetElementPtrInst* gep = new GetElementPtrInst( TheStack, indexVec );
-    bb->getInstList().push_back( gep );         // Put GEP in Block
-
-    return gep;
-}
-
-Instruction*
-StackerCompiler::push_value( BasicBlock* bb, Value* val )
-{
-    // Get location of
-    incr_stack_index(bb);
-
-    // Get the stack pointer
-    GetElementPtrInst* gep = cast<GetElementPtrInst>(
-            get_stack_pointer( bb ) );
-
-    // Cast the value to a long .. hopefully it works
-    Instruction::CastOps opcode = 
-       (isa<PointerType>(val->getType()) ? Instruction::PtrToInt :
-        (val->getType()->getPrimitiveSizeInBits() < 64 ? Instruction::SExt :
-         Instruction::BitCast));
-    CastInst* cast_inst = CastInst::create(opcode, val, Type::Int64Ty );
-    bb->getInstList().push_back( cast_inst );
-
-    // Store the value
-    StoreInst* storeop = new StoreInst( cast_inst, gep );
-    bb->getInstList().push_back( storeop );
-
-    return storeop;
-}
-
-Instruction*
-StackerCompiler::push_integer(BasicBlock* bb, int64_t value )
-{
-    // Just push a constant integer value
-    return push_value( bb, ConstantInt::get( Type::Int64Ty, value ) );
-}
-
-Instruction*
-StackerCompiler::pop_integer( BasicBlock*bb )
-{
-    // Get the stack pointer
-    GetElementPtrInst* gep = cast<GetElementPtrInst>(
-        get_stack_pointer( bb ));
-
-    // Load the value
-    LoadInst* load_inst = new LoadInst( gep );
-    bb->getInstList().push_back( load_inst );
-
-    // Decrement the stack index
-    decr_stack_index( bb );
-
-    // Return the value
-    return load_inst;
-}
-
-Instruction*
-StackerCompiler::push_string( BasicBlock* bb, const char* value )
-{
-    // Get length of the string
-    size_t len = strlen( value );
-
-    // Create a type for the string constant. Length is +1 for
-    // the terminating 0.
-    ArrayType* char_array = ArrayType::get( Type::Int8Ty, len + 1 );
-
-    // Create an initializer for the value
-    Constant* initVal = ConstantArray::get( value );
-
-    // Create an internal linkage global variable to hold the constant.
-    GlobalVariable* strconst = new GlobalVariable(
-        char_array,
-        /*isConstant=*/true,
-        GlobalValue::InternalLinkage,
-        /*initializer=*/initVal,
-        "",
-        TheModule
-    );
-
-    // Push the casted value
-    return push_value( bb, strconst );
-}
-
-Instruction*
-StackerCompiler::pop_string( BasicBlock* bb )
-{
-    // Get location of stack pointer
-    GetElementPtrInst* gep = cast<GetElementPtrInst>(
-        get_stack_pointer( bb ));
-
-    // Load the value from the stack
-    LoadInst* loader = new LoadInst( gep );
-    bb->getInstList().push_back( loader );
-
-    // Cast the integer to a sbyte*
-    CastInst* caster = 
-      new IntToPtrInst(loader, PointerType::get(Type::Int8Ty));
-    bb->getInstList().push_back( caster );
-
-    // Decrement stack index
-    decr_stack_index( bb );
-
-    // Return the value
-    return caster;
-}
-
-Instruction*
-StackerCompiler::replace_top( BasicBlock* bb, Value* new_top, Value* index = 0 )
-{
-    // Get the stack pointer
-    GetElementPtrInst* gep = cast<GetElementPtrInst>(
-            get_stack_pointer( bb, index ));
-
-    // Store the value there
-    StoreInst* store_inst = new StoreInst( new_top, gep );
-    bb->getInstList().push_back( store_inst );
-
-    // Return the value
-    return store_inst;
-}
-
-Instruction*
-StackerCompiler::stack_top( BasicBlock* bb, Value* index = 0 )
-{
-    // Get the stack pointer
-    GetElementPtrInst* gep = cast<GetElementPtrInst>(
-        get_stack_pointer( bb, index ));
-
-    // Load the value
-    LoadInst* load_inst = new LoadInst( gep );
-    bb->getInstList().push_back( load_inst );
-
-    // Return the value
-    return load_inst;
-}
-
-Instruction*
-StackerCompiler::stack_top_string( BasicBlock* bb, Value* index = 0 )
-{
-    // Get location of stack pointer
-    GetElementPtrInst* gep = cast<GetElementPtrInst>(
-        get_stack_pointer( bb, index ));
-
-    // Load the value from the stack
-    LoadInst* loader = new LoadInst( gep );
-    bb->getInstList().push_back( loader );
-
-    // Cast the integer to a sbyte*
-    CastInst* caster = 
-      new IntToPtrInst(loader, PointerType::get(Type::Int8Ty) );
-    bb->getInstList().push_back( caster );
-
-    // Return the value
-    return caster;
-}
-
-static void
-add_block( Function*f, BasicBlock* bb )
-{
-    if ( ! f->empty() && f->back().getTerminator() == 0 )
-    {
-        BranchInst* branch = new BranchInst(bb);
-        f->back().getInstList().push_back( branch );
-    }
-    f->getBasicBlockList().push_back( bb );
-}
-
-
-//===----------------------------------------------------------------------===//
-//            handleXXX - Handle semantics of parser productions
-//===----------------------------------------------------------------------===//
-
-Module*
-StackerCompiler::handle_module_start( )
-{
-    // Return the newly created module
-    return TheModule;
-}
-
-Module*
-StackerCompiler::handle_module_end( Module* mod )
-{
-    // Return the module.
-    return mod;
-}
-
-Module*
-StackerCompiler::handle_definition_list_start()
-{
-    return TheModule;
-}
-
-Module*
-StackerCompiler::handle_definition_list_end( Module* mod, Function* definition )
-{
-    if ( ! definition->empty() )
-    {
-        BasicBlock& last_block = definition->back();
-        if ( last_block.getTerminator() == 0 )
-        {
-            last_block.getInstList().push_back( new ReturnInst() );
-        }
-    }
-    // Insert the definition into the module
-    mod->getFunctionList().push_back( definition );
-
-    // Bump our (sample) statistic.
-    ++NumDefinitions;
-    return mod;
-}
-
-Function*
-StackerCompiler::handle_main_definition( Function* func )
-{
-    // Set the name of the function defined as the Stacker main
-    // This will get called by the "main" that is defined in
-    // the runtime library.
-    func->setName( "_MAIN_");
-
-    // Turn "_stack_" into an initialized variable since this is the main
-    // module. This causes it to not be "external" but defined in this module.
-    TheStack->setInitializer( Constant::getNullValue(stack_type) );
-    TheStack->setLinkage( GlobalValue::LinkOnceLinkage );
-
-    // Turn "_index_" into an intialized variable for the same reason.
-    TheIndex->setInitializer( Constant::getNullValue(Type::Int64Ty) );
-    TheIndex->setLinkage( GlobalValue::LinkOnceLinkage );
-
-    return func;
-}
-
-Function*
-StackerCompiler::handle_forward( char * name )
-{
-    // Just create a placeholder function
-    Function* the_function = new Function (
-        DefinitionType,
-        GlobalValue::ExternalLinkage,
-        name );
-    assert( the_function->isExternal() );
-
-    free( name );
-    return the_function;
-}
-
-Function*
-StackerCompiler::handle_definition( char * name, Function* f )
-{
-    // Look up the function name in the module to see if it was forward
-    // declared.
-#if 0
-    Function* existing_function = TheModule->getNamedFunction( name );
-
-    // If the function already exists...
-    if ( existing_function )
-    {
-        // Just get rid of the placeholder
-        existing_function->dropAllReferences();
-        delete existing_function;
-    }
-#endif
-
-    // Just set the name of the function now that we know what it is.
-    f->setName( name );
-
-    free( name );
-
-    return f;
-}
-
-Function*
-StackerCompiler::handle_word_list_start()
-{
-    TheFunction = new Function(DefinitionType, GlobalValue::ExternalLinkage);
-    return TheFunction;
-}
-
-Function*
-StackerCompiler::handle_word_list_end( Function* f, BasicBlock* bb )
-{
-    add_block( f, bb );
-    return f;
-}
-
-BasicBlock*
-StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
-{
-    // Create a basic block for the preamble
-    BasicBlock* bb = new BasicBlock((echo?"if":""));
-
-    // Get the condition value
-    LoadInst* cond = cast<LoadInst>( pop_integer(bb) );
-
-    // Compare the condition against 0
-    ICmpInst* cond_inst = new ICmpInst( ICmpInst::ICMP_NE, cond,
-        ConstantInt::get( Type::Int64Ty, 0) );
-    bb->getInstList().push_back( cond_inst );
-
-    // Create an exit block
-    BasicBlock* exit_bb = new BasicBlock((echo?"endif":""));
-
-    // Create the true_block
-    BasicBlock* true_bb = new BasicBlock((echo?"then":""));
-
-    // Create the false_block
-    BasicBlock* false_bb = 0;
-    if ( ifFalse ) false_bb = new BasicBlock((echo?"else":""));
-
-    // Create a branch on the ICmp
-    BranchInst* br_inst = new BranchInst( true_bb,
-        ( ifFalse ? false_bb : exit_bb ), cond_inst );
-    bb->getInstList().push_back( br_inst );
-
-    // Fill the true block
-    std::vector<Value*> args;
-    if ( Function* true_func = TheModule->getNamedFunction(ifTrue) )
-    {
-        true_bb->getInstList().push_back(
-                new CallInst( true_func, args ) );
-        true_bb->getInstList().push_back(
-                new BranchInst( exit_bb ) );
-    }
-    else
-    {
-        ThrowException(std::string("Function '") + ifTrue +
-            "' must be declared first.'");
-    }
-
-    free( ifTrue );
-
-    // Fill the false block
-    if ( false_bb )
-    {
-        if ( Function* false_func = TheModule->getNamedFunction(ifFalse) )
-        {
-            false_bb->getInstList().push_back(
-                    new CallInst( false_func, args ) );
-            false_bb->getInstList().push_back(
-                    new BranchInst( exit_bb ) );
-        }
-        else
-        {
-            ThrowException(std::string("Function '") + ifFalse +
-                    "' must be declared first.'");
-        }
-        free( ifFalse );
-    }
-
-    // Add the blocks to the function
-    add_block( TheFunction, bb );
-    add_block( TheFunction, true_bb );
-    if ( false_bb ) add_block( TheFunction, false_bb );
-
-    return exit_bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_while( char* todo )
-{
-
-    // Create a basic block for the loop test
-    BasicBlock* test = new BasicBlock((echo?"while":""));
-
-    // Create an exit block
-    BasicBlock* exit = new BasicBlock((echo?"end":""));
-
-    // Create a loop body block
-    BasicBlock* body = new BasicBlock((echo?"do":""));
-
-    // Create a root node
-    BasicBlock* bb = new BasicBlock((echo?"root":""));
-    BranchInst* root_br_inst = new BranchInst( test );
-    bb->getInstList().push_back( root_br_inst );
-
-    // Examine the condition value
-    LoadInst* cond = cast<LoadInst>( stack_top(test) );
-
-    // Compare the condition against 0
-    ICmpInst* cond_inst = new ICmpInst(
-        ICmpInst::ICMP_NE, cond, ConstantInt::get( Type::Int64Ty, 0));
-    test->getInstList().push_back( cond_inst );
-
-    // Add the branch instruction
-    BranchInst* br_inst = new BranchInst( body, exit, cond_inst );
-    test->getInstList().push_back( br_inst );
-
-    // Fill in the body
-    std::vector<Value*> args;
-    if ( Function* body_func = TheModule->getNamedFunction(todo) )
-    {
-        body->getInstList().push_back( new CallInst( body_func, args ) );
-        body->getInstList().push_back( new BranchInst( test ) );
-    }
-    else
-    {
-        ThrowException(std::string("Function '") + todo +
-            "' must be declared first.'");
-    }
-
-    free( todo );
-
-    // Add the blocks
-    add_block( TheFunction, bb );
-    add_block( TheFunction, test );
-    add_block( TheFunction, body );
-
-    return exit;
-}
-
-BasicBlock*
-StackerCompiler::handle_identifier( char * name )
-{
-    Function* func = TheModule->getNamedFunction( name );
-    BasicBlock* bb = new BasicBlock((echo?"call":""));
-    if ( func )
-    {
-        CallInst* call_def = new CallInst( func , no_arguments );
-        bb->getInstList().push_back( call_def );
-    }
-    else
-    {
-        ThrowException(std::string("Definition '") + name +
-            "' must be defined before it can be used.");
-    }
-
-    free( name );
-    return bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_string( char * value )
-{
-    // Create a new basic block for the push operation
-    BasicBlock* bb = new BasicBlock((echo?"string":""));
-
-    // Push the string onto the stack
-    push_string(bb, value);
-
-    // Free the strdup'd string
-    free( value );
-
-    return bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_integer( const int64_t value )
-{
-    // Create a new basic block for the push operation
-    BasicBlock* bb = new BasicBlock((echo?"int":""));
-
-    // Push the integer onto the stack
-    push_integer(bb, value );
-
-    return bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_word( int tkn )
-{
-    // Create a new basic block to hold the instruction(s)
-    BasicBlock* bb = new BasicBlock();
-
-    /* Fill the basic block with the appropriate instructions */
-    switch ( tkn )
-    {
-    case DUMP :  // Dump the stack (debugging aid)
-    {
-        if (echo) bb->setName("DUMP");
-        Constant * f = TheModule->getOrInsertFunction(
-            "_stacker_dump_stack_", DefinitionType);
-        std::vector<Value*> args;
-        bb->getInstList().push_back( new CallInst( f, args ) );
-        break;
-    }
-
-    // Logical Operations
-    case TRUETOK :  // -- -1
-    {
-        if (echo) bb->setName("TRUE");
-        push_integer(bb,-1);
-        break;
-    }
-    case FALSETOK : // -- 0
-    {
-        if (echo) bb->setName("FALSE");
-        push_integer(bb,0);
-        break;
-    }
-    case LESS : // w1 w2 -- w2<w1
-    {
-        if (echo) bb->setName("LESS");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SLT, op1, op2 );
-        bb->getInstList().push_back( cond_inst );
-        push_value( bb, cond_inst );
-        break;
-    }
-    case MORE : // w1 w2 -- w2>w1
-    {
-        if (echo) bb->setName("MORE");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SGT, op1, op2 );
-        bb->getInstList().push_back( cond_inst );
-        push_value( bb, cond_inst );
-        break;
-    }
-    case LESS_EQUAL : // w1 w2 -- w2<=w1
-    {
-        if (echo) bb->setName("LE");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SLE, op1, op2 );
-        bb->getInstList().push_back( cond_inst );
-        push_value( bb, cond_inst );
-        break;
-    }
-    case MORE_EQUAL : // w1 w2 -- w2>=w1
-    {
-        if (echo) bb->setName("GE");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SGE, op1, op2 );
-        bb->getInstList().push_back( cond_inst );
-        push_value( bb, cond_inst );
-        break;
-    }
-    case NOT_EQUAL : // w1 w2 -- w2!=w1
-    {
-        if (echo) bb->setName("NE");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_NE, op1, op2 );
-        bb->getInstList().push_back( cond_inst );
-        push_value( bb, cond_inst );
-        break;
-    }
-    case EQUAL : // w1 w2 -- w1==w2
-    {
-        if (echo) bb->setName("EQ");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_EQ, op1, op2 );
-        bb->getInstList().push_back( cond_inst );
-        push_value( bb, cond_inst );
-        break;
-    }
-
-    // Arithmetic Operations
-    case PLUS : // w1 w2 -- w2+w1
-    {
-        if (echo) bb->setName("ADD");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* addop =
-            BinaryOperator::create( Instruction::Add, op1, op2);
-        bb->getInstList().push_back( addop );
-        push_value( bb, addop );
-        break;
-    }
-    case MINUS : // w1 w2 -- w2-w1
-    {
-        if (echo) bb->setName("SUB");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* subop =
-            BinaryOperator::create( Instruction::Sub, op1, op2);
-        bb->getInstList().push_back( subop );
-        push_value( bb, subop );
-        break;
-    }
-    case INCR :  // w1 -- w1+1
-    {
-        if (echo) bb->setName("INCR");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* addop =
-            BinaryOperator::create( Instruction::Add, op1, One );
-        bb->getInstList().push_back( addop );
-        push_value( bb, addop );
-        break;
-    }
-    case DECR : // w1 -- w1-1
-    {
-        if (echo) bb->setName("DECR");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* subop = BinaryOperator::create( Instruction::Sub, op1,
-            ConstantInt::get( Type::Int64Ty, 1 ) );
-        bb->getInstList().push_back( subop );
-        push_value( bb, subop );
-        break;
-    }
-    case MULT : // w1 w2 -- w2*w1
-    {
-        if (echo) bb->setName("MUL");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* multop =
-            BinaryOperator::create( Instruction::Mul, op1, op2);
-        bb->getInstList().push_back( multop );
-        push_value( bb, multop );
-        break;
-    }
-    case DIV :// w1 w2 -- w2/w1
-    {
-        if (echo) bb->setName("DIV");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* divop =
-            BinaryOperator::create( Instruction::SDiv, op1, op2);
-        bb->getInstList().push_back( divop );
-        push_value( bb, divop );
-        break;
-    }
-    case MODULUS : // w1 w2 -- w2%w1
-    {
-        if (echo) bb->setName("MOD");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* divop =
-            BinaryOperator::create( Instruction::SRem, op1, op2);
-        bb->getInstList().push_back( divop );
-        push_value( bb, divop );
-        break;
-    }
-    case STAR_SLASH : // w1 w2 w3 -- (w3*w2)/w1
-    {
-        if (echo) bb->setName("STAR_SLASH");
-        // Get the operands
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op3 = cast<LoadInst>(pop_integer(bb));
-
-        // Multiply the first two
-        BinaryOperator* multop =
-            BinaryOperator::create( Instruction::Mul, op1, op2);
-        bb->getInstList().push_back( multop );
-
-        // Divide by the third operand
-        BinaryOperator* divop =
-            BinaryOperator::create( Instruction::SDiv, multop, op3);
-        bb->getInstList().push_back( divop );
-
-        // Push the result
-        push_value( bb, divop );
-
-        break;
-    }
-    case NEGATE : // w1 -- -w1
-    {
-        if (echo) bb->setName("NEG");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        // APPARENTLY, the following doesn't work:
-        // BinaryOperator* negop = BinaryOperator::createNeg( op1 );
-        // bb->getInstList().push_back( negop );
-        // So we'll multiply by -1 (ugh)
-        BinaryOperator* multop = BinaryOperator::create( Instruction::Mul, op1,
-            ConstantInt::get( Type::Int64Ty, -1 ) );
-        bb->getInstList().push_back( multop );
-        push_value( bb, multop );
-        break;
-    }
-    case ABS : // w1 -- |w1|
-    {
-        if (echo) bb->setName("ABS");
-        // Get the top of stack value
-        LoadInst* op1 = cast<LoadInst>(stack_top(bb));
-
-        // Determine if its negative
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SLT, op1, Zero );
-        bb->getInstList().push_back( cond_inst );
-
-        // Create a block for storing the result
-        BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
-
-        // Create a block for making it a positive value
-        BasicBlock* pos_bb = new BasicBlock((echo?"neg":""));
-
-        // Create the branch on the ICmp
-        BranchInst* br_inst = new BranchInst( pos_bb, exit_bb, cond_inst );
-        bb->getInstList().push_back( br_inst );
-
-        // Fill out the negation block
-        LoadInst* pop_op = cast<LoadInst>( pop_integer(pos_bb) );
-        BinaryOperator* neg_op = BinaryOperator::createNeg( pop_op );
-        pos_bb->getInstList().push_back( neg_op );
-        push_value( pos_bb, neg_op );
-        pos_bb->getInstList().push_back( new BranchInst( exit_bb ) );
-
-        // Add the new blocks in the correct order
-        add_block( TheFunction, bb );
-        add_block( TheFunction, pos_bb );
-        bb = exit_bb;
-        break;
-    }
-    case MIN : // w1 w2 -- (w2<w1?w2:w1)
-    {
-        if (echo) bb->setName("MIN");
-
-        // Create the three blocks
-        BasicBlock* exit_bb  = new BasicBlock((echo?"exit":""));
-        BasicBlock* op1_block = new BasicBlock((echo?"less":""));
-        BasicBlock* op2_block = new BasicBlock((echo?"more":""));
-
-        // Get the two operands
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-
-        // Compare them
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SLT, op1, op2);
-        bb->getInstList().push_back( cond_inst );
-
-        // Create a branch on the ICmp
-        BranchInst* br_inst =
-            new BranchInst( op1_block, op2_block, cond_inst );
-        bb->getInstList().push_back( br_inst );
-
-        // Create a block for pushing the first one
-        push_value(op1_block, op1);
-        op1_block->getInstList().push_back( new BranchInst( exit_bb ) );
-
-        // Create a block for pushing the second one
-        push_value(op2_block, op2);
-        op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
-
-        // Add the blocks
-        add_block( TheFunction, bb );
-        add_block( TheFunction, op1_block );
-        add_block( TheFunction, op2_block );
-        bb = exit_bb;
-        break;
-    }
-    case MAX : // w1 w2 -- (w2>w1?w2:w1)
-    {
-        if (echo) bb->setName("MAX");
-        // Get the two operands
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-
-        // Compare them
-        ICmpInst* cond_inst =
-            new ICmpInst( ICmpInst::ICMP_SGT, op1, op2);
-        bb->getInstList().push_back( cond_inst );
-
-        // Create an exit block
-        BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
-
-        // Create a block for pushing the larger one
-        BasicBlock* op1_block = new BasicBlock((echo?"more":""));
-        push_value(op1_block, op1);
-        op1_block->getInstList().push_back( new BranchInst( exit_bb ) );
-
-        // Create a block for pushing the smaller or equal one
-        BasicBlock* op2_block = new BasicBlock((echo?"less":""));
-        push_value(op2_block, op2);
-        op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
-
-        // Create a banch on the ICmp
-        BranchInst* br_inst =
-            new BranchInst( op1_block, op2_block, cond_inst );
-        bb->getInstList().push_back( br_inst );
-
-        // Add the blocks
-        add_block( TheFunction, bb );
-        add_block( TheFunction, op1_block );
-        add_block( TheFunction, op2_block );
-
-        bb = exit_bb;
-        break;
-    }
-
-    // Bitwise Operators
-    case AND : // w1 w2 -- w2&w1
-    {
-        if (echo) bb->setName("AND");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* andop =
-            BinaryOperator::create( Instruction::And, op1, op2);
-        bb->getInstList().push_back( andop );
-        push_value( bb, andop );
-        break;
-    }
-    case OR : // w1 w2 -- w2|w1
-    {
-        if (echo) bb->setName("OR");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* orop =
-            BinaryOperator::create( Instruction::Or, op1, op2);
-        bb->getInstList().push_back( orop );
-        push_value( bb, orop );
-        break;
-    }
-    case XOR : // w1 w2 -- w2^w1
-    {
-        if (echo) bb->setName("XOR");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        BinaryOperator* xorop =
-            BinaryOperator::create( Instruction::Xor, op1, op2);
-        bb->getInstList().push_back( xorop );
-        push_value( bb, xorop );
-        break;
-    }
-    case LSHIFT : // w1 w2 -- w1<<w2
-    {
-        if (echo) bb->setName("SHL");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        CastInst* castop = new TruncInst( op1, Type::Int8Ty );
-        bb->getInstList().push_back( castop );
-        ShiftInst* shlop = new ShiftInst( Instruction::Shl, op2, castop );
-        bb->getInstList().push_back( shlop );
-        push_value( bb, shlop );
-        break;
-    }
-    case RSHIFT :  // w1 w2 -- w1>>w2
-    {
-        if (echo) bb->setName("SHR");
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-        LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
-        CastInst* castop = new TruncInst( op1, Type::Int8Ty );
-        bb->getInstList().push_back( castop );
-        ShiftInst* shrop = new ShiftInst( Instruction::AShr, op2, castop );
-        bb->getInstList().push_back( shrop );
-        push_value( bb, shrop );
-        break;
-    }
-
-    // Stack Manipulation Operations
-    case DROP:          // w --
-    {
-        if (echo) bb->setName("DROP");
-        decr_stack_index(bb, One);
-        break;
-    }
-    case DROP2: // w1 w2 --
-    {
-        if (echo) bb->setName("DROP2");
-        decr_stack_index( bb, Two );
-        break;
-    }
-    case NIP:   // w1 w2 -- w2
-    {
-        if (echo) bb->setName("NIP");
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
-        decr_stack_index( bb  );
-        replace_top( bb, w2 );
-        break;
-    }
-    case NIP2:  // w1 w2 w3 w4 -- w3 w4
-    {
-        if (echo) bb->setName("NIP2");
-        LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
-        decr_stack_index( bb, Two );
-        replace_top( bb, w4 );
-        replace_top( bb, w3, One );
-        break;
-    }
-    case DUP:   // w -- w w
-    {
-        if (echo) bb->setName("DUP");
-        LoadInst* w = cast<LoadInst>( stack_top( bb ) );
-        push_value( bb, w );
-        break;
-    }
-    case DUP2:  // w1 w2 -- w1 w2 w1 w2
-    {
-        if (echo) bb->setName("DUP2");
-        LoadInst* w2 = cast<LoadInst>( stack_top(bb) );
-        LoadInst* w1 = cast<LoadInst>( stack_top(bb, One ) );
-        incr_stack_index( bb, Two );
-        replace_top( bb, w1, One );
-        replace_top( bb, w2 );
-        break;
-    }
-    case SWAP:  // w1 w2 -- w2 w1
-    {
-        if (echo) bb->setName("SWAP");
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
-        replace_top( bb, w1 );
-        replace_top( bb, w2, One );
-        break;
-    }
-    case SWAP2: // w1 w2 w3 w4 -- w3 w4 w1 w2
-    {
-        if (echo) bb->setName("SWAP2");
-        LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three ) );
-        replace_top( bb, w2 );
-        replace_top( bb, w1, One );
-        replace_top( bb, w4, Two );
-        replace_top( bb, w3, Three );
-        break;
-    }
-    case OVER:  // w1 w2 -- w1 w2 w1
-    {
-        if (echo) bb->setName("OVER");
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
-        push_value( bb, w1 );
-        break;
-    }
-    case OVER2: // w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2
-    {
-        if (echo) bb->setName("OVER2");
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three ) );
-        incr_stack_index( bb, Two );
-        replace_top( bb, w2 );
-        replace_top( bb, w1, One );
-        break;
-    }
-    case ROT:   // w1 w2 w3 -- w2 w3 w1
-    {
-        if (echo) bb->setName("ROT");
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, One ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Two ) );
-        replace_top( bb, w1 );
-        replace_top( bb, w3, One );
-        replace_top( bb, w2, Two );
-        break;
-    }
-    case ROT2:  // w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2
-    {
-        if (echo) bb->setName("ROT2");
-        LoadInst* w6 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w5 = cast<LoadInst>( stack_top( bb, One ) );
-        LoadInst* w4 = cast<LoadInst>( stack_top( bb, Two ) );
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb, Three) );
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, Four ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Five ) );
-        replace_top( bb, w2 );
-        replace_top( bb, w1, One );
-        replace_top( bb, w6, Two );
-        replace_top( bb, w5, Three );
-        replace_top( bb, w4, Four );
-        replace_top( bb, w3, Five );
-        break;
-    }
-    case RROT:  // w1 w2 w3 -- w3 w1 w2
-    {
-        if (echo) bb->setName("RROT2");
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, One ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Two ) );
-        replace_top( bb, w2 );
-        replace_top( bb, w1, One );
-        replace_top( bb, w3, Two );
-        break;
-    }
-    case RROT2: // w1 w2 w3 w4 w5 w6 -- w5 w6 w1 w2 w3 w4
-    {
-        if (echo) bb->setName("RROT2");
-        LoadInst* w6 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w5 = cast<LoadInst>( stack_top( bb, One ) );
-        LoadInst* w4 = cast<LoadInst>( stack_top( bb, Two ) );
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb, Three) );
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, Four ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Five ) );
-        replace_top( bb, w4 );
-        replace_top( bb, w3, One );
-        replace_top( bb, w2, Two );
-        replace_top( bb, w1, Three );
-        replace_top( bb, w6, Four );
-        replace_top( bb, w5, Five );
-        break;
-    }
-    case TUCK:  // w1 w2 -- w2 w1 w2
-    {
-        if (echo) bb->setName("TUCK");
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
-        incr_stack_index( bb );
-        replace_top( bb, w2 );
-        replace_top( bb, w1, One );
-        replace_top( bb, w2, Two );
-        break;
-    }
-    case TUCK2: // w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4
-    {
-        if (echo) bb->setName("TUCK2");
-        LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
-        LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
-        LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
-        LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three) );
-        incr_stack_index( bb, Two );
-        replace_top( bb, w4 );
-        replace_top( bb, w3, One );
-        replace_top( bb, w2, Two );
-        replace_top( bb, w1, Three );
-        replace_top( bb, w4, Four );
-        replace_top( bb, w3, Five );
-        break;
-    }
-    case ROLL:  // x0 x1 .. xn n -- x1 .. xn x0
-    {
-        /// THIS OEPRATOR IS OMITTED PURPOSEFULLY AND IS LEFT TO THE
-        /// READER AS AN EXERCISE. THIS IS ONE OF THE MORE COMPLICATED
-        /// OPERATORS. IF YOU CAN GET THIS ONE RIGHT, YOU COMPLETELY
-        /// UNDERSTAND HOW BOTH LLVM AND STACKER WOR.
-        /// HINT: LOOK AT PICK AND SELECT. ROLL IS SIMILAR.
-        if (echo) bb->setName("ROLL");
-        break;
-    }
-    case PICK:  // x0 ... Xn n -- x0 ... Xn x0
-    {
-        if (echo) bb->setName("PICK");
-        LoadInst* n = cast<LoadInst>( stack_top( bb ) );
-        BinaryOperator* addop =
-            BinaryOperator::create( Instruction::Add, n, One );
-        bb->getInstList().push_back( addop );
-        LoadInst* x0 = cast<LoadInst>( stack_top( bb, addop ) );
-        replace_top( bb, x0 );
-        break;
-    }
-    case SELECT:        // m n X0..Xm Xm+1 .. Xn -- Xm
-    {
-        if (echo) bb->setName("SELECT");
-        LoadInst* m = cast<LoadInst>( stack_top(bb) );
-        LoadInst* n = cast<LoadInst>( stack_top(bb, One) );
-        BinaryOperator* index =
-            BinaryOperator::create( Instruction::Add, m, One );
-        bb->getInstList().push_back( index );
-        LoadInst* Xm = cast<LoadInst>( stack_top(bb, index ) );
-        BinaryOperator* n_plus_1 =
-            BinaryOperator::create( Instruction::Add, n, One );
-        bb->getInstList().push_back( n_plus_1 );
-        decr_stack_index( bb, n_plus_1 );
-        replace_top( bb, Xm );
-        break;
-    }
-    case MALLOC : // n -- p
-    {
-        if (echo) bb->setName("MALLOC");
-        // Get the number of bytes to mallocate
-        LoadInst* op1 = cast<LoadInst>( pop_integer(bb) );
-
-        // Make sure its a UIntTy
-        CastInst* caster = CastInst::createTruncOrBitCast( op1, Type::Int32Ty );
-        bb->getInstList().push_back( caster );
-
-        // Allocate the bytes
-        MallocInst* mi = new MallocInst( Type::Int8Ty, caster );
-        bb->getInstList().push_back( mi );
-
-        // Push the pointer
-        push_value( bb, mi );
-        break;
-    }
-    case FREE :  // p --
-    {
-        if (echo) bb->setName("FREE");
-        // Pop the value off the stack
-        CastInst* ptr = cast<CastInst>( pop_string(bb) );
-
-        // Free the memory
-        FreeInst* fi = new FreeInst( ptr );
-        bb->getInstList().push_back( fi );
-
-        break;
-    }
-    case GET : // p w1 -- p w2
-    {
-        if (echo) bb->setName("GET");
-        // Get the character index
-        LoadInst* op1 = cast<LoadInst>( stack_top(bb) );
-        CastInst* chr_idx = CastInst::createSExtOrBitCast( op1, Type::Int64Ty );
-        bb->getInstList().push_back( chr_idx );
-
-        // Get the String pointer
-        CastInst* ptr = cast<CastInst>( stack_top_string(bb,One) );
-
-        // Get address of op1'th element of the string
-        std::vector<Value*> indexVec;
-        indexVec.push_back( chr_idx );
-        GetElementPtrInst* gep = new GetElementPtrInst( ptr, indexVec );
-        bb->getInstList().push_back( gep );
-
-        // Get the value and push it
-        LoadInst* loader = new LoadInst( gep );
-        bb->getInstList().push_back( loader );
-        CastInst* caster = CastInst::createTruncOrBitCast(loader, Type::Int32Ty);
-        bb->getInstList().push_back( caster );
-
-        // Push the result back on stack
-        replace_top( bb, caster );
-
-        break;
-    }
-    case PUT : // p w2 w1  -- p
-    {
-        if (echo) bb->setName("PUT");
-
-        // Get the value to put
-        LoadInst* w1 = cast<LoadInst>( pop_integer(bb) );
-
-        // Get the character index
-        LoadInst* w2 = cast<LoadInst>( pop_integer(bb) );
-        CastInst* chr_idx = CastInst::createSExtOrBitCast( w2, Type::Int64Ty );
-        bb->getInstList().push_back( chr_idx );
-
-        // Get the String pointer
-        CastInst* ptr = cast<CastInst>( stack_top_string(bb) );
-
-        // Get address of op2'th element of the string
-        std::vector<Value*> indexVec;
-        indexVec.push_back( chr_idx );
-        GetElementPtrInst* gep = new GetElementPtrInst( ptr, indexVec );
-        bb->getInstList().push_back( gep );
-
-        // Cast the value and put it
-        CastInst* caster = new TruncInst( w1, Type::Int8Ty );
-        bb->getInstList().push_back( caster );
-        StoreInst* storer = new StoreInst( caster, gep );
-        bb->getInstList().push_back( storer );
-
-        break;
-    }
-    case RECURSE :
-    {
-        if (echo) bb->setName("RECURSE");
-        std::vector<Value*> params;
-        CallInst* call_inst = new CallInst( TheFunction, params );
-        bb->getInstList().push_back( call_inst );
-        break;
-    }
-    case RETURN :
-    {
-        if (echo) bb->setName("RETURN");
-        bb->getInstList().push_back( new ReturnInst() );
-        break;
-    }
-    case EXIT :
-    {
-        if (echo) bb->setName("EXIT");
-        // Get the result value
-        LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
-
-        // Cast down to an integer
-        CastInst* caster = new TruncInst( op1, Type::Int32Ty );
-        bb->getInstList().push_back( caster );
-
-        // Call exit(3)
-        std::vector<Value*> params;
-        params.push_back(caster);
-        CallInst* call_inst = new CallInst( TheExit, params );
-        bb->getInstList().push_back( call_inst );
-        break;
-    }
-    case TAB :
-    {
-        if (echo) bb->setName("TAB");
-        // Get the format string for a character
-        std::vector<Value*> indexVec;
-        indexVec.push_back( Zero );
-        indexVec.push_back( Zero );
-        GetElementPtrInst* format_gep =
-            new GetElementPtrInst( ChrFormat, indexVec );
-        bb->getInstList().push_back( format_gep );
-
-        // Get the character to print (a tab)
-        ConstantInt* newline = ConstantInt::get(Type::Int32Ty,
-            static_cast<int>('\t'));
-
-        // Call printf
-        std::vector<Value*> args;
-        args.push_back( format_gep );
-        args.push_back( newline );
-        bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
-        break;
-    }
-    case SPACE :
-    {
-        if (echo) bb->setName("SPACE");
-        // Get the format string for a character
-        std::vector<Value*> indexVec;
-        indexVec.push_back( Zero );
-        indexVec.push_back( Zero );
-        GetElementPtrInst* format_gep =
-            new GetElementPtrInst( ChrFormat, indexVec );
-        bb->getInstList().push_back( format_gep );
-
-        // Get the character to print (a space)
-        ConstantInt* newline = ConstantInt::get(Type::Int32Ty,
-            static_cast<int>(' '));
-
-        // Call printf
-        std::vector<Value*> args;
-        args.push_back( format_gep );
-        args.push_back( newline );
-        bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
-        break;
-    }
-    case CR :
-    {
-        if (echo) bb->setName("CR");
-        // Get the format string for a character
-        std::vector<Value*> indexVec;
-        indexVec.push_back( Zero );
-        indexVec.push_back( Zero );
-        GetElementPtrInst* format_gep =
-            new GetElementPtrInst( ChrFormat, indexVec );
-        bb->getInstList().push_back( format_gep );
-
-        // Get the character to print (a newline)
-        ConstantInt* newline = ConstantInt::get(Type::Int32Ty,
-            static_cast<int>('\n'));
-
-        // Call printf
-        std::vector<Value*> args;
-        args.push_back( format_gep );
-        args.push_back( newline );
-        bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
-        break;
-    }
-    case IN_STR :
-    {
-        if (echo) bb->setName("IN_STR");
-        // Make room for the value result
-        incr_stack_index(bb);
-        GetElementPtrInst* gep_value =
-          cast<GetElementPtrInst>(get_stack_pointer(bb));
-        CastInst* caster = 
-          new BitCastInst(gep_value, PointerType::get(Type::Int8Ty));
-
-        // Make room for the count result
-        incr_stack_index(bb);
-        GetElementPtrInst* gep_count =
-            cast<GetElementPtrInst>(get_stack_pointer(bb));
-
-        // Call scanf(3)
-        std::vector<Value*> args;
-        args.push_back( InStrFormat );
-        args.push_back( caster );
-        CallInst* scanf = new CallInst( TheScanf, args );
-        bb->getInstList().push_back( scanf );
-
-        // Store the result
-        bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
-        break;
-    }
-    case IN_NUM :
-    {
-        if (echo) bb->setName("IN_NUM");
-        // Make room for the value result
-        incr_stack_index(bb);
-        GetElementPtrInst* gep_value =
-            cast<GetElementPtrInst>(get_stack_pointer(bb));
-
-        // Make room for the count result
-        incr_stack_index(bb);
-        GetElementPtrInst* gep_count =
-            cast<GetElementPtrInst>(get_stack_pointer(bb));
-
-        // Call scanf(3)
-        std::vector<Value*> args;
-        args.push_back( InStrFormat );
-        args.push_back( gep_value );
-        CallInst* scanf = new CallInst( TheScanf, args );
-        bb->getInstList().push_back( scanf );
-
-        // Store the result
-        bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
-        break;
-    }
-    case IN_CHAR :
-    {
-        if (echo) bb->setName("IN_CHAR");
-        // Make room for the value result
-        incr_stack_index(bb);
-        GetElementPtrInst* gep_value =
-            cast<GetElementPtrInst>(get_stack_pointer(bb));
-
-        // Make room for the count result
-        incr_stack_index(bb);
-        GetElementPtrInst* gep_count =
-            cast<GetElementPtrInst>(get_stack_pointer(bb));
-
-        // Call scanf(3)
-        std::vector<Value*> args;
-        args.push_back( InChrFormat );
-        args.push_back( gep_value );
-        CallInst* scanf = new CallInst( TheScanf, args );
-        bb->getInstList().push_back( scanf );
-
-        // Store the result
-        bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
-        break;
-    }
-    case OUT_STR :
-    {
-        if (echo) bb->setName("OUT_STR");
-        LoadInst* op1 = cast<LoadInst>(stack_top(bb));
-
-        // Get the address of the format string
-        std::vector<Value*> indexVec;
-        indexVec.push_back( Zero );
-        indexVec.push_back( Zero );
-        GetElementPtrInst* format_gep =
-            new GetElementPtrInst( StrFormat, indexVec );
-        bb->getInstList().push_back( format_gep );
-        // Build function call arguments
-        std::vector<Value*> args;
-        args.push_back( format_gep );
-        args.push_back( op1 );
-        // Call printf
-        bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
-        break;
-    }
-    case OUT_NUM :
-    {
-        if (echo) bb->setName("OUT_NUM");
-        // Pop the numeric operand off the stack
-        LoadInst* op1 = cast<LoadInst>(stack_top(bb));
-
-        // Get the address of the format string
-        std::vector<Value*> indexVec;
-        indexVec.push_back( Zero );
-        indexVec.push_back( Zero );
-        GetElementPtrInst* format_gep =
-            new GetElementPtrInst( NumFormat, indexVec );
-        bb->getInstList().push_back( format_gep );
-
-        // Build function call arguments
-        std::vector<Value*> args;
-        args.push_back( format_gep );
-        args.push_back( op1 );
-
-        // Call printf
-        bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
-        break;
-    }
-    case OUT_CHAR :
-    {
-        if (echo) bb->setName("OUT_CHAR");
-        // Pop the character operand off the stack
-        LoadInst* op1 = cast<LoadInst>(stack_top(bb));
-
-        // Get the address of the format string
-        std::vector<Value*> indexVec;
-        indexVec.push_back( Zero );
-        indexVec.push_back( Zero );
-        GetElementPtrInst* format_gep =
-            new GetElementPtrInst( ChrFormat, indexVec );
-        bb->getInstList().push_back( format_gep );
-
-        // Build function call arguments
-        std::vector<Value*> args;
-        args.push_back( format_gep );
-        args.push_back( op1 );
-        // Call printf
-        bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
-        break;
-    }
-    default :
-    {
-        ThrowException(std::string("Compiler Error: Unhandled token #"));
-    }
-    }
-
-    // Return the basic block
-    return bb;
-}