Initial stacker checkin
authorChris Lattner <sabre@nondot.org>
Sun, 23 Nov 2003 17:52:55 +0000 (17:52 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 23 Nov 2003 17:52:55 +0000 (17:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10178 91177308-0d34-0410-b5e6-96231b3b80d8

projects/Stacker/lib/compiler/Lexer.l [new file with mode: 0644]
projects/Stacker/lib/compiler/Makefile [new file with mode: 0644]
projects/Stacker/lib/compiler/README [new file with mode: 0644]
projects/Stacker/lib/compiler/StackerCompiler.cpp [new file with mode: 0644]
projects/Stacker/lib/compiler/StackerCompiler.h [new file with mode: 0644]
projects/Stacker/lib/compiler/StackerParser.y [new file with mode: 0644]

diff --git a/projects/Stacker/lib/compiler/Lexer.l b/projects/Stacker/lib/compiler/Lexer.l
new file mode 100644 (file)
index 0000000..6087f88
--- /dev/null
@@ -0,0 +1,234 @@
+/*===-- Lexer.l - Scanner for Stacker language -----------------*- 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 flex scanner for Stacker languages files.
+//
+//===----------------------------------------------------------------------===*/
+
+%option prefix="Stacker"
+%option yylineno
+%option nostdinit
+%option never-interactive
+%option batch
+%option noyywrap
+%option nodefault
+%option 8bit
+%option outfile="Lexer.cpp"
+%option ecs
+%option noreject
+%option noyymore
+
+%{
+
+#include "StackerCompiler.h"
+#include "StackerParser.h"
+
+/* Conversion of text ints to binary */
+static uint64_t IntToVal(const char *Buffer) {
+  uint64_t Result = 0;
+  for (; *Buffer; Buffer++) {
+    uint64_t OldRes = Result;
+    Result *= 10;
+    Result += *Buffer-'0';
+    if (Result < OldRes)   // Uh, oh, overflow detected!!!
+      StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
+  }
+  return Result;
+}
+
+/* Conversion of text hexadecimal ints to binary */
+static uint64_t HexIntToVal(const char *Buffer) {
+  uint64_t Result = 0;
+  for (; *Buffer; ++Buffer) {
+    uint64_t OldRes = Result;
+    Result *= 16;
+    char C = *Buffer;
+    if (C >= '0' && C <= '9')
+      Result += C-'0';
+    else if (C >= 'A' && C <= 'F')
+      Result += C-'A'+10;
+    else if (C >= 'a' && C <= 'f')
+      Result += C-'a'+10;
+
+    if (Result < OldRes)   // Uh, oh, overflow detected!!!
+      StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
+  }
+  return Result;
+}
+
+#define YY_NEVER_INTERACTIVE 1
+%}
+
+/* Comments start with a ; and go till end of line */
+Comment1       [#].*$
+/* You can also embed them in ( ... ) */
+Comment2       \(.*\)
+/* We ignore white space */
+White          [ \t\n]
+
+/* jdentifiers start with a % sign */
+Identifier     [A-Za-z][-A-Za-z0-9_]*
+
+/* Strings can contain any character except " and \ */
+String         \"[^\"]*\"
+
+/* Positive and negative integer constants*/
+PInteger       [+]?[0-9]+
+NInteger       -[0-9]+
+HexInteger     0x[0-9A-Fa-f]+
+
+/* Special Characters - name them to avoid flex confusion */
+Semi           [;]
+Colon          [:]
+Less           \<
+More           \>
+LessEq         \<\=
+MoreEq         \>\=
+NotEq          \<\>
+Equal          \=
+Plus           \+
+Minus          \-
+Incr           \+\+
+Decr           \-\-
+Mult           \*
+Div            \/
+StarSlash      \*\/
+LShift         \<\<
+RShift         \>\>
+InStr          \<s
+InNum          \<d
+InChar         \<c
+OutStr         \>s
+OutNum         \>d
+OutChar                \>c
+
+%%
+
+{Comment1}     { /* Ignore comments */ }
+{Comment2}     { /* Ignore comments */ }
+
+{Colon}                { return COLON; }
+{Semi}         { return SEMI; }
+
+TRUE           { return TRUE; }
+FALSE          { return FALSE; }
+ON             { return TRUE; }
+OFF            { return FALSE; }
+{Less}         { return LESS; }
+LT             { return LESS; }
+{More}         { return MORE; }
+GT             { return MORE; }
+{LessEq}       { return LESS_EQUAL; }
+LE             { return LESS_EQUAL; }
+{MoreEq}       { return MORE_EQUAL; }
+GE             { return MORE_EQUAL; }
+{NotEq}                { return NOT_EQUAL; }
+NE             { return NOT_EQUAL; }
+{Equal}                { return EQUAL; }
+EQ             { return EQUAL; }
+
+{Plus}         { return PLUS; }
+{Minus}                { return MINUS; }
+{Incr}         { return INCR; }
+{Decr}         { return DECR; }
+{Mult}         { return MULT; }
+{Div}          { return DIV; }
+MOD            { return MODULUS; }
+NEG            { return NEGATE; }
+ABS            { return ABS; }
+MIN            { return MIN; }
+MAX            { return MAX; }
+{StarSlash}    { return STAR_SLASH; }
+
+AND            { return AND; }
+OR             { return OR; }
+XOR            { return XOR; }
+{LShift}       { return LSHIFT; }
+{RShift}       { return RSHIFT; }
+
+DROP           { return DROP; }
+NIP            { return NIP; }
+DUP            { return DUP; }
+SWAP           { return SWAP; }
+OVER           { return OVER; }
+PICK           { return PICK; }
+SELECT         { return SELECT; }
+ROT            { return ROT; }
+RROT           { return RROT; }
+ROLL           { return ROLL; }
+TUCK           { return TUCK; }
+DROP2          { return DROP2; }
+NIP2           { return NIP2; }
+DUP2           { return DUP2; }
+SWAP2          { return SWAP2; }
+OVER2          { return OVER2; }
+TUCK2          { return TUCK2; }
+ROT2           { return ROT2; }
+RROT2          { return RROT2; }
+
+MALLOC         { return MALLOC; }
+FREE           { return FREE; }
+GET            { return GET; }
+PUT            { return PUT; }
+
+IF             { return IF; }
+ELSE           { return ELSE; }
+ENDIF          { return ENDIF; }
+WHILE          { return WHILE; }
+END            { return END; }
+
+RECURSE                { return RECURSE; }
+RETURN         { return RETURN; }
+EXIT           { return EXIT; }
+FORWARD                { return FORWARD; }
+TAB            { return TAB; }
+SPACE          { return SPACE; }
+CR             { return CR; }
+
+{InStr}                { return IN_STR; }
+{InNum}                { return IN_NUM; }
+{InChar}       { return IN_CHAR; }
+
+{OutStr}       { return OUT_STR; }
+{OutNum}       { return OUT_NUM; }
+{OutChar}      { return OUT_CHAR; }
+
+MAIN           { return MAIN; }
+
+DUMP           { return DUMP; }
+
+!=             { StackerCompiler::ThrowException(
+                 "You probably meant to use a <> instead of !=" ); }
+
+==             { StackerCompiler::ThrowException(
+                 "You probably meant to use a single = .. this isn't C"); }
+
+{PInteger}      { Stackerlval.IntegerVal = IntToVal(yytext); return INTEGER; }
+{NInteger}      { uint64_t Val = IntToVal(yytext+1);
+                 // +1:  we have bigger negative range
+                 if (Val > (uint64_t)INT64_MAX+1)
+                   StackerCompiler::ThrowException(
+                   "Constant too large for signed 64 bits!");
+                  Stackerlval.IntegerVal = -Val; 
+                 return INTEGER; 
+                }
+{HexInteger}   { Stackerlval.IntegerVal = HexIntToVal(yytext+3); 
+                   return INTEGER;
+                }
+
+{String}       { yytext[strlen(yytext)-1] = 0;           // nuke end quote
+                 Stackerlval.StringVal = strdup(yytext+1);  // Nuke start quote
+                 return STRING;
+                }
+
+{Identifier}    { Stackerlval.StringVal = strdup(yytext); return IDENTIFIER; }
+
+{White}         { /* Ignore whitespace */ }
+%%
diff --git a/projects/Stacker/lib/compiler/Makefile b/projects/Stacker/lib/compiler/Makefile
new file mode 100644 (file)
index 0000000..4c89ca8
--- /dev/null
@@ -0,0 +1,21 @@
+##===- projects/sample/lib/sample/Makefile -----------------*- Makefile -*-===##
+
+#
+# Indicate where we are relative to the top of the source tree.
+#
+LEVEL=../../../..
+
+#
+# Give the name of a library.  This will build a dynamic version.
+#
+SHARED_LIBRARY=1
+LIBRARYNAME=stkr_compiler
+
+#
+# Include Makefile.common so we know what to do.
+#
+include $(LEVEL)/Makefile.common
+
+ifdef PARSE_DEBUG
+INCLUDES += -DPARSE_DEBUG
+endif
diff --git a/projects/Stacker/lib/compiler/README b/projects/Stacker/lib/compiler/README
new file mode 100644 (file)
index 0000000..5f13cbb
--- /dev/null
@@ -0,0 +1,20 @@
+This directory contains a sample language front end for LLVM.
+
+It is a *very* simple/crude implementation of FORTH. It has many
+deficiencies but provides enough basics to give you an idea of 
+what programming a new language front end for LLVM  looks like.
+
+To keep things simple, Stacker has the following limitations:
+1. Only a single, global stack is manipulated.
+2. There is no interpretation, everything is compiled.
+3. There's no type/bounds checking .. you're on your own.
+4. There's no floating point support.
+5. Only stdin can be read. Only stdout can be written. No other 
+   file I/O is supported.
+
+As such, this isn't a very useful language for anything other than
+the most trivial of programs. It is, however, a good learning tool
+(for both the author and the student).
+
+Reid Spencer
+16 November 2003
diff --git a/projects/Stacker/lib/compiler/StackerCompiler.cpp b/projects/Stacker/lib/compiler/StackerCompiler.cpp
new file mode 100644 (file)
index 0000000..6ebcae9
--- /dev/null
@@ -0,0 +1,1728 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//            Globasl - Global variables we use 
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/iMemory.h>
+#include <llvm/iOperators.h>
+#include <llvm/iOther.h>
+#include <llvm/iTerminators.h>
+#include <Support/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;
+
+static Statistic<> NumDefinitions(
+       "numdefs","The # of definitions encoutered while compiling Stacker");
+
+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)
+    , IZero(0)
+    , IOne(0)
+    , ITwo(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,
+    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)
+       {
+           throw ParseException(filename, 
+               "Could not open file '" + filename + "'");
+       }
+    }
+
+    Module *Result;
+    try 
+    {
+       // Create the module we'll return
+       TheModule = new Module( CurFilename );
+
+       // Create a type to represent the stack. This is the same as the LLVM 
+       // Assembly type [ 256 x int ]
+       stack_type = ArrayType::get( Type::IntTy, 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::AppendingLinkage, 
+           /*initializer=*/0, 
+           /*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::LongTy, 
+           /*isConstant=*/false,
+           /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+           /*initializer=*/0, 
+           /*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::SByteTy ) );
+       FunctionType* printf_type = 
+           FunctionType::get( Type::IntTy, 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::IntTy );
+       FunctionType* exit_type = 
+           FunctionType::get( Type::VoidTy, params, false );
+       TheExit = new Function( 
+           exit_type, GlobalValue::ExternalLinkage, "exit", TheModule);
+
+       ConstantArray* str_format = ConstantArray::get("%s");
+       StrFormat = new GlobalVariable( 
+           /*type=*/ArrayType::get( Type::SByteTy,  3 ),
+           /*isConstant=*/true,
+           /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+           /*initializer=*/str_format, 
+           /*name=*/"_str_format_",
+           /*parent=*/TheModule
+       );
+
+       ConstantArray* in_str_format = ConstantArray::get(" %as");
+       InStrFormat = new GlobalVariable( 
+           /*type=*/ArrayType::get( Type::SByteTy,  5 ),
+           /*isConstant=*/true,
+           /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+           /*initializer=*/in_str_format, 
+           /*name=*/"_in_str_format_",
+           /*parent=*/TheModule
+       );
+
+       ConstantArray* num_format = ConstantArray::get("%d");
+       NumFormat = new GlobalVariable( 
+           /*type=*/ArrayType::get( Type::SByteTy,  3 ),
+           /*isConstant=*/true,
+           /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+           /*initializer=*/num_format, 
+           /*name=*/"_num_format_",
+           /*parent=*/TheModule
+       );
+
+       ConstantArray* in_num_format = ConstantArray::get(" %d");
+       InNumFormat = new GlobalVariable( 
+           /*type=*/ArrayType::get( Type::SByteTy,  4 ),
+           /*isConstant=*/true,
+           /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+           /*initializer=*/in_num_format, 
+           /*name=*/"_in_num_format_",
+           /*parent=*/TheModule
+       );
+
+       ConstantArray* chr_format = ConstantArray::get("%c");
+       ChrFormat = new GlobalVariable( 
+           /*type=*/ArrayType::get( Type::SByteTy,  3 ),
+           /*isConstant=*/true,
+           /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+           /*initializer=*/chr_format, 
+           /*name=*/"_chr_format_",
+           /*parent=*/TheModule
+       );
+
+       ConstantArray* in_chr_format = ConstantArray::get(" %c");
+       InChrFormat = new GlobalVariable( 
+           /*type=*/ArrayType::get( Type::SByteTy,  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::LongTy, 0 );
+       One = ConstantInt::get( Type::LongTy, 1 );
+       Two = ConstantInt::get( Type::LongTy, 2 );
+       Three = ConstantInt::get( Type::LongTy, 3 );
+       Four = ConstantInt::get( Type::LongTy, 4 );
+       Five = ConstantInt::get( Type::LongTy, 5 );
+       IZero = ConstantInt::get( Type::IntTy, 0 );
+       IOne = ConstantInt::get( Type::IntTy, 1 );
+       ITwo = ConstantInt::get( Type::IntTy, 2 );
+
+       // 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 StackCompiler via the "handle*" methods 
+       Stackerparse(); 
+
+       // Avoid potential illegal use (TheInstance might be on the stack)
+       TheInstance = 0;
+
+    } 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 = new CastInst( ival, Type::LongTy );
+    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 = new CastInst( ival, Type::LongTy );
+    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 = new CastInst( index, Type::LongTy );
+       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 an integer .. hopefully it works
+    CastInst* cast_inst = new CastInst( val, Type::IntTy );
+    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, int32_t value )
+{
+    // Just push a constant integer value
+    return push_value( bb, ConstantSInt::get( Type::IntTy, 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::SByteTy, len + 1 );
+
+    // Create an initializer for the value
+    ConstantArray* 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 CastInst( loader, PointerType::get(Type::SByteTy) );
+    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 CastInst( loader, PointerType::get(Type::SByteTy) );
+    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
+    func->setName( "_MAIN_");
+
+    // Create the actual main for the runtime system.
+    //std::vector<const Type*> params; // No parameters
+    //FunctionType* main_type = FunctionType::get( Type::IntTy, params, false );
+    Function* SystemMain = new Function(
+       DefinitionType, 
+       GlobalValue::ExternalLinkage,
+       "main", TheModule);
+
+    // Create a basic block that just calls the STACKERMAIN function. Note
+    // that the basic block is automatically inserted into the end of SystemMain
+    BasicBlock* bb = new BasicBlock( (echo?"main":"a"), SystemMain ) ;
+    bb->getInstList().push_back( new CallInst( func, no_arguments) );
+    bb->getInstList().push_back( new ReturnInst() ); 
+
+    // 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) );
+
+    // Turn "_index_" into an intialized variable for the same reason.
+    TheIndex->setInitializer( Constant::getNullValue(Type::LongTy) );
+    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.
+    Function* existing_function = TheModule->getNamedFunction( name );
+
+#if 0
+    // 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 
+    SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond, 
+       ConstantSInt::get( Type::IntTy, 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 SetCond
+    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 );
+
+    // Pop the condition value
+    LoadInst* cond = cast<LoadInst>( stack_top(test) );
+
+    // Compare the condition against 0 
+    SetCondInst* cond_inst = new SetCondInst( 
+       Instruction::SetNE, cond, ConstantSInt::get( Type::IntTy, 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 int32_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");
+       Function* f = TheModule->getOrInsertFunction(
+           "_stacker_dump_stack_", DefinitionType);
+       std::vector<Value*> args;
+       bb->getInstList().push_back( new CallInst( f, args ) );
+       break;
+    }
+
+    // Logical Operations
+    case TRUE :  // -- -1
+    {
+       if (echo) bb->setName("TRUE");
+       push_integer(bb,-1); 
+       break;
+    }
+    case FALSE : // -- 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));
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetLT, 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));
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetGT, 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));
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetLE, 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));
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetGE, 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));
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetNE, 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));
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetEQ, 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, IOne );
+       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,
+           ConstantSInt::get( Type::IntTy, 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::Div, 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::Rem, 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::Div, 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,
+           ConstantSInt::get( Type::IntTy, -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
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetLT, op1, IZero );
+       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 SetCond
+       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 
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetLT, op1, op2);
+       bb->getInstList().push_back( cond_inst );
+
+       // Create a branch on the SetCond
+       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 
+       SetCondInst* cond_inst = 
+           new SetCondInst( Instruction::SetGT, 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 SetCond
+       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 CastInst( op1, Type::UByteTy );
+       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 CastInst( op1, Type::UByteTy );
+       bb->getInstList().push_back( castop );
+       ShiftInst* shrop = new ShiftInst( Instruction::Shr, 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, IOne );
+       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, IOne );
+       bb->getInstList().push_back( index );
+       LoadInst* Xm = cast<LoadInst>( stack_top(bb, index ) );
+       BinaryOperator* n_plus_1 = 
+           BinaryOperator::create( Instruction::Add, n, IOne );
+       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 = new CastInst( op1, Type::UIntTy );
+       bb->getInstList().push_back( caster );
+
+       // Allocate the bytes
+       MallocInst* mi = new MallocInst( Type::SByteTy, 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 = new CastInst( op1, Type::LongTy );
+       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 = new CastInst( loader, Type::IntTy );
+       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 = new CastInst( w2, Type::LongTy );
+       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 CastInst( w1, Type::SByteTy );
+       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));
+
+       // Call exit(3)
+       std::vector<Value*> params;
+       params.push_back(op1);
+       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 newline)
+       ConstantSInt* newline = ConstantSInt::get(Type::IntTy, 
+           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 newline)
+       ConstantSInt* newline = ConstantSInt::get(Type::IntTy, 
+           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)
+       ConstantSInt* newline = ConstantSInt::get(Type::IntTy, 
+           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 CastInst( gep_value, PointerType::get( Type::SByteTy ) );
+
+       // 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;
+}
diff --git a/projects/Stacker/lib/compiler/StackerCompiler.h b/projects/Stacker/lib/compiler/StackerCompiler.h
new file mode 100644 (file)
index 0000000..9e35fa8
--- /dev/null
@@ -0,0 +1,224 @@
+//===-- StackerCompiler.h - Interface to the Stacker Compiler ---*- 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 header file defines the various variables that are shared among the 
+//  different components of the parser...
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_STACKERCOMPILER_H
+#define LLVM_STACKERCOMPILER_H
+
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Instruction.h>
+#include <llvm/Module.h>
+#include <llvm/Assembly/Parser.h>
+#include <Support/StringExtras.h>
+
+using namespace llvm;
+
+// Global variables exported from the lexer...
+extern std::FILE *Stackerin;
+extern int Stackerlineno;
+extern char* Stackertext;
+extern int Stackerleng;
+
+/// @brief This class provides the Compiler for the Stacker language. 
+/// 
+/// The main method to call is \c compile. The other methods are
+/// all internal to the compiler and protected. In general the 
+/// handle_* methods are called by the BISON generated parser
+/// (see StackerParser.y). The methods returning Instruction* all
+/// produce some snippet of code to manipulate the stack in some
+/// way. These functions are just conveniences as they are used
+/// often by the compiler.
+class StackerCompiler
+{
+    /// @name Constructors and Operators
+    /// @{
+    public:
+       /// Default Constructor
+       StackerCompiler();
+
+       /// Destructor
+       ~StackerCompiler();
+    private:
+       /// Do not copy StackerCompilers
+       StackerCompiler(const StackerCompiler&);
+
+       /// Do not copy StackerCompilers.
+       StackerCompiler& operator=(const StackerCompiler& );
+
+    /// @}
+    /// @name High Level Interface
+    /// @{
+    public:
+       /// @brief Compile a single file to LLVM bytecode.
+       ///
+       /// To use the StackerCompiler, just create one on
+       /// the stack and call this method.
+       Module* compile( 
+           const std::string& filename, ///< File to compile
+           bool echo, ///< Causes compiler to echo output
+           size_t stack_size ); ///< Size of generated stack
+    /// @}
+    /// @name Accessors
+    /// @{
+    public:
+       /// @brief Returns the name of the file being compiled.
+       std::string& filename() { return CurFilename; }
+
+    /// @}
+    /// @name Parse Handling Methods
+    /// @{
+    private:
+       /// Allow only the parser to access these methods. No
+       /// one else should call them.
+       friend int Stackerparse();
+
+       /// @brief Handle the start of a module
+       Module* handle_module_start();
+
+       /// @brief Handle the end of a module
+       /// @param mod The module we're defining.
+       Module* handle_module_end( Module* mod );
+
+       /// @brief Handle the start of a list of definitions
+       Module* handle_definition_list_start( );
+
+       /// @brief Handle the end of a list of definitions
+       /// @param mod The module we're constructing
+       /// @param definition A definition (function) to add to the module
+       Module* handle_definition_list_end( Module* mod, Function* definition );
+
+       /// @brief Handle creation of the MAIN definition
+       /// @param func The function to be used as the MAIN definition
+       Function* handle_main_definition( Function* func );
+
+       /// @brief Handle a forward definition
+       /// @param name The name of the definition being declared
+       Function* handle_forward( char* name );
+
+       /// @brief Handle a general definition
+       /// @param name The name of the definition being defined
+       /// @param func The Function definition.
+       Function* handle_definition( char* name, Function* func );
+
+       /// @brief Handle the start of a definition's word list
+       Function* handle_word_list_start();
+
+       /// @brief Handle the end of a definition's word list
+       /// @param func The function to which the basic block is added
+       /// @param next The block to add to the function
+       Function* handle_word_list_end( Function* func, BasicBlock* next );
+
+       /// @brief Handle an if statement, possibly without an else
+       /// @brief ifTrue The block to execute if true
+       /// @brief ifFalse The optional block to execute if false
+       BasicBlock* handle_if( char* ifTrue, char* ifFalse = 0 );
+
+       /// @brief Handle a while statement
+       /// @brief todo The block to repeatedly execute
+       BasicBlock* handle_while( char* todo );
+
+       /// @brief Handle an identifier to call the identified definition
+       /// @param name The name of the identifier to be called.
+       BasicBlock* handle_identifier( char * name );
+
+       /// @brief Handle the push of a string onto the stack
+       /// @param value The string to be pushed.
+       BasicBlock* handle_string( char * value );
+
+       /// @brief Handle the push of an integer onto the stack.
+       /// @param value The integer value to be pushed.
+       BasicBlock* handle_integer( const int32_t value );
+
+       /// @brief Handle one of the reserved words (given as a token)
+       BasicBlock* handle_word( int tkn );
+
+    /// @}
+    /// @name Utility functions
+    /// @{
+    public:
+        /// @brief Throws an exception to indicate an error
+        /// @param message The message to be output
+       /// @param line Override for the current line no
+       static inline void ThrowException( const std::string &message, 
+               int line = -1)      
+       {
+         if (line == -1) line = Stackerlineno;
+         // TODO: column number in exception
+         throw ParseException(TheInstance->CurFilename, message, line);
+       }
+    private:
+       /// @brief Generate code to increment the stack index
+       Instruction* incr_stack_index( BasicBlock* bb, Value* );
+       /// @brief Generate code to decrement the stack index.
+       Instruction* decr_stack_index( BasicBlock* bb, Value* );
+       /// @brief Generate code to dereference the top of stack.
+       Instruction* get_stack_pointer( BasicBlock* bb, Value* );
+       /// @brief Generate code to push any value onto the stack.
+       Instruction* push_value( BasicBlock* bb, Value* value );
+       /// @brief Generate code to push a constant integer onto the stack.
+       Instruction* push_integer( BasicBlock* bb, int32_t value );
+       /// @brief Generate code to pop an integer off the stack.
+       Instruction* pop_integer( BasicBlock* bb );
+       /// @brief Generate code to push a string pointer onto the stack.
+       Instruction* push_string( BasicBlock* bb, const char* value );
+       /// @brief Generate code to pop a string pointer off the stack.
+       Instruction* pop_string( BasicBlock* bb );
+       /// @brief Generate code to get the top stack element.
+       Instruction* stack_top( BasicBlock* bb, Value* index );
+       /// @brief Generate code to get the top stack element as a string.
+       Instruction* stack_top_string( BasicBlock* bb, Value* index );
+       /// @brief Generate code to replace the top element of the stack.
+       Instruction* replace_top( BasicBlock* bb, Value* new_top, Value* index);
+
+    /// @}
+    /// @name Data Members (used during parsing)
+    /// @{
+    public:
+        static StackerCompiler*        TheInstance;    ///< The instance for the parser
+
+    private:
+       std::string             CurFilename;    ///< Current file name
+       Module*                 TheModule;      ///< Module instance we'll build
+        Function*              TheFunction;    ///< Function we're building
+       FunctionType*           DefinitionType; ///< FT for Definitions
+       GlobalVariable*         TheStack;       ///< For referencing _stack_
+       GlobalVariable*         TheIndex;       ///< For referencing _index_
+       Function*               TheScanf;       ///< External input function
+       Function*               ThePrintf;      ///< External output function
+       Function*               TheExit;        ///< External exit function
+       GlobalVariable*         StrFormat;      ///< Format for strings
+       GlobalVariable*         NumFormat;      ///< Format for numbers
+       GlobalVariable*         ChrFormat;      ///< Format for chars
+       GlobalVariable*         InStrFormat;    ///< Format for input strings
+       GlobalVariable*         InNumFormat;    ///< Format for input numbers
+       GlobalVariable*         InChrFormat;    ///< Format for input chars
+       ConstantInt*            Zero;           ///< long constant 0
+       ConstantInt*            One;            ///< long constant 1
+       ConstantInt*            Two;            ///< long constant 2
+       ConstantInt*            Three;          ///< long constant 3
+       ConstantInt*            Four;           ///< long constant 4
+       ConstantInt*            Five;           ///< long constant 5
+       ConstantInt*            IZero;          ///< int constant 0
+       ConstantInt*            IOne;           ///< int constant 1
+       ConstantInt*            ITwo;           ///< int constant 2
+       std::vector<Value*>     no_arguments;   ///< no arguments for Stacker
+       bool                    echo;           ///< Echo flag
+       size_t                  stack_size;     ///< Size of stack to gen.
+       ArrayType*              stack_type;     ///< The type of the stack
+    /// @}
+};
+
+#endif
diff --git a/projects/Stacker/lib/compiler/StackerParser.y b/projects/Stacker/lib/compiler/StackerParser.y
new file mode 100644 (file)
index 0000000..3c82a86
--- /dev/null
@@ -0,0 +1,190 @@
+//===-- llvmAsmParser.y - Parser for llvm assembly files --------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the bison parser for LLVM assembly languages files.
+//
+//===----------------------------------------------------------------------===//
+
+%debug
+
+%{
+#include "StackerCompiler.h"
+#include "llvm/SymbolTable.h"
+#include "llvm/Module.h"
+#include "llvm/iTerminators.h"
+#include "llvm/iMemory.h"
+#include "llvm/iOperators.h"
+#include "llvm/iPHINode.h"
+#include "Support/STLExtras.h"
+#include "Support/DepthFirstIterator.h"
+#include <list>
+#include <utility>
+#include <algorithm>
+
+#define YYERROR_VERBOSE 1
+#define SCI StackerCompiler::TheInstance
+
+int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
+int yylex();                       // declaration" of xxx warnings.
+int yyparse();
+
+%}
+
+%union 
+{
+  llvm::Module*                ModuleVal;
+  llvm::Function*      FunctionVal;
+  llvm::BasicBlock*    BasicBlockVal;
+  uint32_t              IntegerVal;
+  char*                 StringVal;
+}
+
+/* Typed Productions */
+%type <ModuleVal>      Module DefinitionList
+%type <FunctionVal>    Definition ForwardDef ColonDef MainDef
+%type <FunctionVal>    WordList
+%type <BasicBlockVal>  Word
+
+/* Typed Tokens */
+%token <IntegerVal>    INTEGER
+%token <StringVal>     STRING IDENTIFIER
+
+/* Terminal Tokens */
+%token                         SEMI COLON FORWARD MAIN DUMP
+%token                 TRUE FALSE LESS MORE LESS_EQUAL MORE_EQUAL NOT_EQUAL EQUAL
+%token                         PLUS MINUS INCR DECR MULT DIV MODULUS NEGATE ABS MIN MAX STAR_SLASH 
+%token                         AND OR XOR LSHIFT RSHIFT 
+%token                         DROP DROP2 NIP NIP2 DUP DUP2 SWAP SWAP2 OVER OVER2 ROT ROT2 
+%token                 RROT RROT2 TUCK TUCK2 ROLL PICK SELECT
+%token                         MALLOC FREE GET PUT
+%token                         IF ELSE ENDIF WHILE END RECURSE RETURN EXIT
+%token                         TAB SPACE CR IN_STR IN_NUM IN_CHAR OUT_STR OUT_NUM OUT_CHAR
+
+/* Start Token */
+%start Module
+
+%%
+
+/* A module is just a DefinitionList */
+Module                 :                               { SCI->handle_module_start( ); } 
+               DefinitionList                  { $$ = SCI->handle_module_end( $2 ); } ;
+
+/* A Definitionlist is just a sequence of definitions */
+DefinitionList : DefinitionList Definition     { $$ = SCI->handle_definition_list_end( $1, $2 ); }
+               | /* empty */                   { $$ = SCI->handle_definition_list_start(); } ;
+
+/* A definition can be one of three flavors */
+Definition     : ForwardDef                    { $$ = $1; }
+               | ColonDef                      { $$ = $1; }
+               | MainDef                       { $$ = $1; } ;
+
+/* Forward definitions just introduce a name */
+ForwardDef : FORWARD IDENTIFIER SEMI           { $$ = SCI->handle_forward( $2 ); } ;
+
+/* The main definition has to generate additional code so we treat it specially */
+MainDef : COLON MAIN WordList SEMI             { $$ = SCI->handle_main_definition($3); } ;
+
+/* Regular definitions have a name and a WordList */
+ColonDef : COLON IDENTIFIER WordList SEMI      { $$ = SCI->handle_definition( $2, $3 ); } ;
+
+/* A WordList is just a sequence of words */
+WordList : WordList Word                       { $$ = SCI->handle_word_list_end( $1, $2 ); } 
+        | /* empty */                          { $$ = SCI->handle_word_list_start() } ;
+
+/* A few "words" have a funky syntax */
+/* FIXME: The body of compound words can currently only be function calls */
+/* This is not acceptable, it should be a WordList, but that produces a Function */
+/* Which is hard to merge into the function the compound statement is working on */
+Word : IF IDENTIFIER ELSE IDENTIFIER ENDIF     { $$ = SCI->handle_if( $2, $4 ); } 
+     | IF IDENTIFIER ENDIF                     { $$ = SCI->handle_if( $2 ); } 
+     | WHILE IDENTIFIER END                    { $$ = SCI->handle_while( $2 ); } ;
+
+/* A few words are handled specially */
+Word : IDENTIFIER                              { $$ = SCI->handle_identifier( $1 ); } ;
+Word : STRING                                  { $$ = SCI->handle_string( $1 ); } ;
+Word : INTEGER                                         { $$ = SCI->handle_integer( $1 ); } ;
+
+/* Everything else is a terminal symbol and goes to handle_word */
+Word : TRUE                                    { $$ = SCI->handle_word( TRUE ); } ;
+Word : FALSE                                   { $$ = SCI->handle_word( FALSE ); } ;
+Word : LESS                                    { $$ = SCI->handle_word( LESS ); } ;
+Word : MORE                                    { $$ = SCI->handle_word( MORE ); } ;
+Word : LESS_EQUAL                              { $$ = SCI->handle_word( LESS_EQUAL ); } ;
+Word : MORE_EQUAL                              { $$ = SCI->handle_word( MORE_EQUAL ); } ;
+Word : NOT_EQUAL                               { $$ = SCI->handle_word( NOT_EQUAL ); } ;
+Word : EQUAL                                   { $$ = SCI->handle_word( EQUAL ); } ;
+Word : PLUS                                    { $$ = SCI->handle_word( PLUS ); } ;
+Word : MINUS                                   { $$ = SCI->handle_word( MINUS ); } ;
+Word : INCR                                    { $$ = SCI->handle_word( INCR ); } ;
+Word : DECR                                    { $$ = SCI->handle_word( DECR ); } ;
+Word : MULT                                    { $$ = SCI->handle_word( MULT ); } ;
+Word : DIV                                     { $$ = SCI->handle_word( DIV ); } ;
+Word : MODULUS                                 { $$ = SCI->handle_word( MODULUS ); } ;
+Word : NEGATE                                  { $$ = SCI->handle_word( NEGATE ); } ;
+Word : ABS                                     { $$ = SCI->handle_word( ABS ); } ;
+Word : MIN                                     { $$ = SCI->handle_word( MIN ); } ;
+Word : MAX                                     { $$ = SCI->handle_word( MAX ); } ;
+Word : STAR_SLASH                              { $$ = SCI->handle_word( STAR_SLASH ); } ;
+Word : AND                                     { $$ = SCI->handle_word( AND ); } ;
+Word : OR                                      { $$ = SCI->handle_word( OR ); } ;
+Word : XOR                                     { $$ = SCI->handle_word( XOR ); } ;
+Word : LSHIFT                                  { $$ = SCI->handle_word( LSHIFT ); } ;
+Word : RSHIFT                                  { $$ = SCI->handle_word( RSHIFT ); } ;
+Word : DROP                                    { $$ = SCI->handle_word( DROP ); } ;
+Word : DROP2                                   { $$ = SCI->handle_word( DROP2 ); } ;
+Word : NIP                                     { $$ = SCI->handle_word( NIP ); } ;
+Word : NIP2                                    { $$ = SCI->handle_word( NIP2 ); } ;
+Word : DUP                                     { $$ = SCI->handle_word( DUP ); } ;
+Word : DUP2                                    { $$ = SCI->handle_word( DUP2 ); } ;
+Word : SWAP                                    { $$ = SCI->handle_word( SWAP ); } ;
+Word : SWAP2                                   { $$ = SCI->handle_word( SWAP2 ); } ;
+Word : OVER                                    { $$ = SCI->handle_word( OVER ); } ;
+Word : OVER2                                   { $$ = SCI->handle_word( OVER2 ); } ;
+Word : ROT                                     { $$ = SCI->handle_word( ROT ); } ;
+Word : ROT2                                    { $$ = SCI->handle_word( ROT2 ); } ;
+Word : RROT                                    { $$ = SCI->handle_word( RROT ); } ;
+Word : RROT2                                   { $$ = SCI->handle_word( RROT2 ); } ;
+Word : TUCK                                    { $$ = SCI->handle_word( TUCK ); } ;
+Word : TUCK2                                   { $$ = SCI->handle_word( TUCK2 ); } ;
+Word : ROLL                                    { $$ = SCI->handle_word( ROLL ); } ;
+Word : PICK                                    { $$ = SCI->handle_word( PICK ); } ;
+Word : SELECT                                  { $$ = SCI->handle_word( SELECT ); } ;
+Word : MALLOC                                  { $$ = SCI->handle_word( MALLOC ); } ;
+Word : FREE                                    { $$ = SCI->handle_word( FREE ); } ;
+Word : GET                                     { $$ = SCI->handle_word( GET ); } ;
+Word : PUT                                     { $$ = SCI->handle_word( PUT ); } ;
+Word : RECURSE                                 { $$ = SCI->handle_word( RECURSE ); } ;
+Word : RETURN                                  { $$ = SCI->handle_word( RETURN ); } ;
+Word : EXIT                                    { $$ = SCI->handle_word( EXIT ); } ;
+Word : TAB                                     { $$ = SCI->handle_word( TAB ); };
+Word : SPACE                                   { $$ = SCI->handle_word( SPACE ); } ;
+Word : CR                                      { $$ = SCI->handle_word( CR ); } ;
+Word : IN_STR                                  { $$ = SCI->handle_word( IN_STR ); } ;
+Word : IN_NUM                                  { $$ = SCI->handle_word( IN_NUM ); } ;
+Word : IN_CHAR                                 { $$ = SCI->handle_word( IN_CHAR ); } ;
+Word : OUT_STR                                 { $$ = SCI->handle_word( OUT_STR ); } ;
+Word : OUT_NUM                                 { $$ = SCI->handle_word( OUT_NUM ); } ;
+Word : OUT_CHAR                                        { $$ = SCI->handle_word( OUT_CHAR ); } ;
+Word : DUMP                                    { $$ = SCI->handle_word( DUMP ); } ;
+
+%%
+
+/* Handle messages a little more nicely than the default yyerror */
+int yyerror(const char *ErrorMsg) {
+  std::string where 
+    = std::string((SCI->filename() == "-") ? std::string("<stdin>") : SCI->filename())
+                  + ":" + utostr((unsigned) Stackerlineno ) + ": ";
+  std::string errMsg = std::string(ErrorMsg) + "\n" + where + " while reading ";
+  if (yychar == YYEMPTY)
+    errMsg += "end-of-file.";
+  else
+    errMsg += "token: '" + std::string(Stackertext, Stackerleng) + "'";
+  StackerCompiler::ThrowException(errMsg);
+  return 0;
+}