aboutsummaryrefslogtreecommitdiff
path: root/projects/Stacker/lib/compiler/StackerCompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'projects/Stacker/lib/compiler/StackerCompiler.cpp')
-rw-r--r--projects/Stacker/lib/compiler/StackerCompiler.cpp1728
1 files changed, 1728 insertions, 0 deletions
diff --git a/projects/Stacker/lib/compiler/StackerCompiler.cpp b/projects/Stacker/lib/compiler/StackerCompiler.cpp
new file mode 100644
index 0000000000..6ebcae9b36
--- /dev/null
+++ b/projects/Stacker/lib/compiler/StackerCompiler.cpp
@@ -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);