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.cpp1806
1 files changed, 0 insertions, 1806 deletions
diff --git a/projects/Stacker/lib/compiler/StackerCompiler.cpp b/projects/Stacker/lib/compiler/StackerCompiler.cpp
deleted file mode 100644
index 1542645b6c..0000000000
--- a/projects/Stacker/lib/compiler/StackerCompiler.cpp
+++ /dev/null
@@ -1,1806 +0,0 @@
-//===-- StackerCompiler.cpp - Parser for llvm assembly files ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by Reid Spencer and donated to the LLVM research
-// group and is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the compiler for the "Stacker" language.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "stacker"
-#include "llvm/PassManager.h"
-#include "llvm/Analysis/LoadValueNumbering.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/Parser.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Instructions.h"
-#include "llvm/ADT/Statistic.h"
-#include "StackerCompiler.h"
-#include "StackerParser.h"
-#include <string>
-
-// Lexer/Parser defined variables and functions
-extern std::FILE *Stackerin;
-extern int Stackerlineno;
-extern char* Stackertext;
-extern int Stackerleng;
-extern int Stackerparse();
-
-StackerCompiler* StackerCompiler::TheInstance = 0;
-
-STATISTIC(NumDefinitions, "The number of definitions encountered");
-
-StackerCompiler::StackerCompiler()
- : CurFilename("")
- , TheModule(0)
- , TheFunction(0)
- , DefinitionType(0)
- , TheStack(0)
- , TheIndex(0)
- , TheScanf(0)
- , ThePrintf(0)
- , TheExit(0)
- , StrFormat(0)
- , NumFormat(0)
- , ChrFormat(0)
- , InStrFormat(0)
- , InNumFormat(0)
- , InChrFormat(0)
- , Zero(0)
- , One(0)
- , Two(0)
- , Three(0)
- , Four(0)
- , Five(0)
- , no_arguments()
- , echo(false)
- , stack_size(256)
- , stack_type(0)
-{
-}
-
-StackerCompiler::~StackerCompiler()
-{
- // delete TheModule; << don't do this!
- // TheModule is passed to caller of the compile() method .. its their
- // problem. Likewise for the other allocated objects (which become part
- // of TheModule.
- TheModule = 0;
- DefinitionType = 0;
- TheStack = 0;
- TheIndex = 0;
-}
-
-Module*
-StackerCompiler::compile(
- const std::string& filename,
- bool should_echo,
- unsigned optLevel,
- size_t the_stack_size
-)
-{
- // TODO: Provide a global lock to protect the singled-threaded compiler
- // and its global variables. Should be in guard object on the stack so
- // that its destructor causes lock to be released (multiple exits from
- // this function).
-
- // Assign parameters
- CurFilename = filename;
- echo = should_echo;
- stack_size = the_stack_size;
-
- /// Default the file to read
- FILE *F = stdin;
-
- ///
- if (filename != "-")
- {
- F = fopen(filename.c_str(), "r");
-
- if (F == 0)
- {
- ParseError Err;
- Err.setError(filename, "Could not open file '" + filename + "'");
- throw Err;
- }
- }
-
- try
- {
- // Create the module we'll return
- TheModule = new Module( CurFilename );
-
- // Tell the module about our runtime library
- TheModule->addLibrary("stkr_runtime");
-
- // Create a type to represent the stack. This is the same as the LLVM
- // Assembly type [ 256 x long ]
- stack_type = ArrayType::get( Type::Int64Ty, stack_size );
-
- // Create a global variable for the stack. Note the use of appending
- // linkage linkage so that multiple modules will make the stack larger.
- // Also note that the last argument causes the global to be inserted
- // automatically into the module.
- TheStack = new GlobalVariable(
- /*type=*/ stack_type,
- /*isConstant=*/ false,
- /*Linkage=*/ GlobalValue::LinkOnceLinkage,
- /*initializer=*/ Constant::getNullValue(stack_type),
- /*name=*/ "_stack_",
- /*parent=*/ TheModule
- );
-
- // Create a global variable for indexing into the stack. Note the use
- // of LinkOnce linkage. Only one copy of _index_ will be retained
- // after linking
- TheIndex = new GlobalVariable(
- /*type=*/Type::Int64Ty,
- /*isConstant=*/false,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/ Constant::getNullValue(Type::Int64Ty),
- /*name=*/"_index_",
- /*parent=*/TheModule
- );
-
- // Create a function prototype for definitions. No parameters, no
- // result. This is used below any time a function is created.
- std::vector<const Type*> params; // No parameters
- DefinitionType = FunctionType::get( Type::VoidTy, params, false );
-
- // Create a function for printf(3)
- params.push_back( PointerType::get( Type::Int8Ty ) );
- FunctionType* printf_type =
- FunctionType::get( Type::Int32Ty, params, true );
- ThePrintf = new Function(
- printf_type, GlobalValue::ExternalLinkage, "printf", TheModule);
-
- // Create a function for scanf(3)
- TheScanf = new Function(
- printf_type, GlobalValue::ExternalLinkage, "scanf", TheModule);
-
- // Create a function for exit(3)
- params.clear();
- params.push_back( Type::Int32Ty );
- FunctionType* exit_type =
- FunctionType::get( Type::VoidTy, params, false );
- TheExit = new Function(
- exit_type, GlobalValue::ExternalLinkage, "exit", TheModule);
-
- Constant* str_format = ConstantArray::get("%s");
- StrFormat = new GlobalVariable(
- /*type=*/ArrayType::get( Type::Int8Ty, 3 ),
- /*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/str_format,
- /*name=*/"_str_format_",
- /*parent=*/TheModule
- );
-
- Constant* in_str_format = ConstantArray::get(" %as");
- InStrFormat = new GlobalVariable(
- /*type=*/ArrayType::get( Type::Int8Ty, 5 ),
- /*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/in_str_format,
- /*name=*/"_in_str_format_",
- /*parent=*/TheModule
- );
-
- Constant* num_format = ConstantArray::get("%d");
- NumFormat = new GlobalVariable(
- /*type=*/ArrayType::get( Type::Int8Ty, 3 ),
- /*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/num_format,
- /*name=*/"_num_format_",
- /*parent=*/TheModule
- );
-
- Constant* in_num_format = ConstantArray::get(" %d");
- InNumFormat = new GlobalVariable(
- /*type=*/ArrayType::get( Type::Int8Ty, 4 ),
- /*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/in_num_format,
- /*name=*/"_in_num_format_",
- /*parent=*/TheModule
- );
-
- Constant* chr_format = ConstantArray::get("%c");
- ChrFormat = new GlobalVariable(
- /*type=*/ArrayType::get( Type::Int8Ty, 3 ),
- /*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/chr_format,
- /*name=*/"_chr_format_",
- /*parent=*/TheModule
- );
-
- Constant* in_chr_format = ConstantArray::get(" %c");
- InChrFormat = new GlobalVariable(
- /*type=*/ArrayType::get( Type::Int8Ty, 4 ),
- /*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/in_chr_format,
- /*name=*/"_in_chr_format_",
- /*parent=*/TheModule
- );
-
- // Get some constants so we aren't always creating them
- Zero = ConstantInt::get( Type::Int64Ty, 0 );
- One = ConstantInt::get( Type::Int64Ty, 1 );
- Two = ConstantInt::get( Type::Int64Ty, 2 );
- Three = ConstantInt::get( Type::Int64Ty, 3 );
- Four = ConstantInt::get( Type::Int64Ty, 4 );
- Five = ConstantInt::get( Type::Int64Ty, 5 );
-
- // Reset the current line number
- Stackerlineno = 1;
-
- // Reset the parser's input to F
- Stackerin = F; // Set the input file.
-
- // Let the parse know about this instance
- TheInstance = this;
-
- // Parse the file. The parser (see StackParser.y) will call back to
- // the StackerCompiler via the "handle*" methods
- Stackerparse();
-
- // Avoid potential illegal use (TheInstance might be on the stack)
- TheInstance = 0;
-
- // Set up a pass manager
- PassManager Passes;
- // Add in the passes we want to execute
- Passes.add(new TargetData(TheModule));
- // Verify we start with valid
- Passes.add(createVerifierPass());
-
- if (optLevel > 0) {
- if (optLevel > 1) {
- // Clean up disgusting code
- Passes.add(createCFGSimplificationPass());
- // Remove unused globals
- Passes.add(createGlobalDCEPass());
- // IP Constant Propagation
- Passes.add(createIPConstantPropagationPass());
- // Clean up after IPCP
- Passes.add(createInstructionCombiningPass());
- // Clean up after IPCP
- Passes.add(createCFGSimplificationPass());
- // Inline small definitions (functions)
- Passes.add(createFunctionInliningPass());
- // Simplify cfg by copying code
- Passes.add(createTailDuplicationPass());
- if (optLevel > 2) {
- // Merge & remove BBs
- Passes.add(createCFGSimplificationPass());
- // Compile silly sequences
- Passes.add(createInstructionCombiningPass());
- // Reassociate expressions
- Passes.add(createReassociatePass());
- // Combine silly seq's
- Passes.add(createInstructionCombiningPass());
- // Eliminate tail calls
- Passes.add(createTailCallEliminationPass());
- // Merge & remove BBs
- Passes.add(createCFGSimplificationPass());
- // Hoist loop invariants
- Passes.add(createLICMPass());
- // Clean up after the unroller
- Passes.add(createInstructionCombiningPass());
- // Canonicalize indvars
- Passes.add(createIndVarSimplifyPass());
- // Unroll small loops
- Passes.add(createLoopUnrollPass());
- // Clean up after the unroller
- Passes.add(createInstructionCombiningPass());
- // GVN for load instructions
- Passes.add(createLoadValueNumberingPass());
- // Remove common subexprs
- Passes.add(createGCSEPass());
- // Constant prop with SCCP
- Passes.add(createSCCPPass());
- }
- if (optLevel > 3) {
- // Run instcombine again after redundancy elimination
- Passes.add(createInstructionCombiningPass());
- // Delete dead stores
- Passes.add(createDeadStoreEliminationPass());
- // SSA based 'Aggressive DCE'
- Passes.add(createAggressiveDCEPass());
- // Merge & remove BBs
- Passes.add(createCFGSimplificationPass());
- // Merge dup global constants
- Passes.add(createConstantMergePass());
- }
- }
-
- // Merge & remove BBs
- Passes.add(createCFGSimplificationPass());
- // Memory To Register
- Passes.add(createPromoteMemoryToRegisterPass());
- // Compile silly sequences
- Passes.add(createInstructionCombiningPass());
- // Make sure everything is still good.
- Passes.add(createVerifierPass());
- }
-
- // Run our queue of passes all at once now, efficiently.
- Passes.run(*TheModule);
-
- } catch (...) {
- if (F != stdin) fclose(F); // Make sure to close file descriptor
- throw; // if an exception is thrown
- }
-
- // Close the file
- if (F != stdin) fclose(F);
-
- // Return the compiled module to the caller
- return TheModule;
-}
-
-//===----------------------------------------------------------------------===//
-// Internal Functions, used by handleXXX below.
-// These represent the basic stack operations.
-//===----------------------------------------------------------------------===//
-
-Instruction*
-StackerCompiler::incr_stack_index( BasicBlock* bb, Value* ival = 0 )
-{
- // Load the value from the TheIndex
- LoadInst* loadop = new LoadInst( TheIndex );
- bb->getInstList().push_back( loadop );
-
- // Increment the loaded index value
- if ( ival == 0 ) ival = One;
- CastInst* caster = CastInst::createSExtOrBitCast( ival, Type::Int64Ty );
- bb->getInstList().push_back( caster );
- BinaryOperator* addop = BinaryOperator::create( Instruction::Add,
- loadop, caster);
- bb->getInstList().push_back( addop );
-
- // Store the incremented value
- StoreInst* storeop = new StoreInst( addop, TheIndex );
- bb->getInstList().push_back( storeop );
- return storeop;
-}
-
-Instruction*
-StackerCompiler::decr_stack_index( BasicBlock* bb, Value* ival = 0 )
-{
- // Load the value from the TheIndex
- LoadInst* loadop = new LoadInst( TheIndex );
- bb->getInstList().push_back( loadop );
-
- // Decrement the loaded index value
- if ( ival == 0 ) ival = One;
- CastInst* caster = CastInst::createSExtOrBitCast( ival, Type::Int64Ty );
- bb->getInstList().push_back( caster );
- BinaryOperator* subop = BinaryOperator::create( Instruction::Sub,
- loadop, caster);
- bb->getInstList().push_back( subop );
-
- // Store the incremented value
- StoreInst* storeop = new StoreInst( subop, TheIndex );
- bb->getInstList().push_back( storeop );
-
- return storeop;
-}
-
-Instruction*
-StackerCompiler::get_stack_pointer( BasicBlock* bb, Value* index = 0 )
-{
- // Load the value of the Stack Index
- LoadInst* loadop = new LoadInst( TheIndex );
- bb->getInstList().push_back( loadop );
-
- // Index into the stack to get its address. NOTE the use of two
- // elements in this vector. The first de-references the pointer that
- // "TheStack" represents. The second indexes into the pointed to array.
- // Think of the first index as getting the address of the 0th element
- // of the array.
- std::vector<Value*> indexVec;
- indexVec.push_back( Zero );
-
- if ( index == 0 )
- {
- indexVec.push_back(loadop);
- }
- else
- {
- CastInst* caster = CastInst::createSExtOrBitCast( index, Type::Int64Ty );
- bb->getInstList().push_back( caster );
- BinaryOperator* subop = BinaryOperator::create(
- Instruction::Sub, loadop, caster );
- bb->getInstList().push_back( subop );
- indexVec.push_back(subop);
- }
-
- // Get the address of the indexed stack element
- GetElementPtrInst* gep = new GetElementPtrInst( TheStack, indexVec );
- bb->getInstList().push_back( gep ); // Put GEP in Block
-
- return gep;
-}
-
-Instruction*
-StackerCompiler::push_value( BasicBlock* bb, Value* val )
-{
- // Get location of
- incr_stack_index(bb);
-
- // Get the stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
- get_stack_pointer( bb ) );
-
- // Cast the value to a long .. hopefully it works
- Instruction::CastOps opcode =
- (isa<PointerType>(val->getType()) ? Instruction::PtrToInt :
- (val->getType()->getPrimitiveSizeInBits() < 64 ? Instruction::SExt :
- Instruction::BitCast));
- CastInst* cast_inst = CastInst::create(opcode, val, Type::Int64Ty );
- bb->getInstList().push_back( cast_inst );
-
- // Store the value
- StoreInst* storeop = new StoreInst( cast_inst, gep );
- bb->getInstList().push_back( storeop );
-
- return storeop;
-}
-
-Instruction*
-StackerCompiler::push_integer(BasicBlock* bb, int64_t value )
-{
- // Just push a constant integer value
- return push_value( bb, ConstantInt::get( Type::Int64Ty, value ) );
-}
-
-Instruction*
-StackerCompiler::pop_integer( BasicBlock*bb )
-{
- // Get the stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
- get_stack_pointer( bb ));
-
- // Load the value
- LoadInst* load_inst = new LoadInst( gep );
- bb->getInstList().push_back( load_inst );
-
- // Decrement the stack index
- decr_stack_index( bb );
-
- // Return the value
- return load_inst;
-}
-
-Instruction*
-StackerCompiler::push_string( BasicBlock* bb, const char* value )
-{
- // Get length of the string
- size_t len = strlen( value );
-
- // Create a type for the string constant. Length is +1 for
- // the terminating 0.
- ArrayType* char_array = ArrayType::get( Type::Int8Ty, len + 1 );
-
- // Create an initializer for the value
- Constant* initVal = ConstantArray::get( value );
-
- // Create an internal linkage global variable to hold the constant.
- GlobalVariable* strconst = new GlobalVariable(
- char_array,
- /*isConstant=*/true,
- GlobalValue::InternalLinkage,
- /*initializer=*/initVal,
- "",
- TheModule
- );
-
- // Push the casted value
- return push_value( bb, strconst );
-}
-
-Instruction*
-StackerCompiler::pop_string( BasicBlock* bb )
-{
- // Get location of stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
- get_stack_pointer( bb ));
-
- // Load the value from the stack
- LoadInst* loader = new LoadInst( gep );
- bb->getInstList().push_back( loader );
-
- // Cast the integer to a sbyte*
- CastInst* caster =
- new IntToPtrInst(loader, PointerType::get(Type::Int8Ty));
- bb->getInstList().push_back( caster );
-
- // Decrement stack index
- decr_stack_index( bb );
-
- // Return the value
- return caster;
-}
-
-Instruction*
-StackerCompiler::replace_top( BasicBlock* bb, Value* new_top, Value* index = 0 )
-{
- // Get the stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
- get_stack_pointer( bb, index ));
-
- // Store the value there
- StoreInst* store_inst = new StoreInst( new_top, gep );
- bb->getInstList().push_back( store_inst );
-
- // Return the value
- return store_inst;
-}
-
-Instruction*
-StackerCompiler::stack_top( BasicBlock* bb, Value* index = 0 )
-{
- // Get the stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
- get_stack_pointer( bb, index ));
-
- // Load the value
- LoadInst* load_inst = new LoadInst( gep );
- bb->getInstList().push_back( load_inst );
-
- // Return the value
- return load_inst;
-}
-
-Instruction*
-StackerCompiler::stack_top_string( BasicBlock* bb, Value* index = 0 )
-{
- // Get location of stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
- get_stack_pointer( bb, index ));
-
- // Load the value from the stack
- LoadInst* loader = new LoadInst( gep );
- bb->getInstList().push_back( loader );
-
- // Cast the integer to a sbyte*
- CastInst* caster =
- new IntToPtrInst(loader, PointerType::get(Type::Int8Ty) );
- bb->getInstList().push_back( caster );
-
- // Return the value
- return caster;
-}
-
-static void
-add_block( Function*f, BasicBlock* bb )
-{
- if ( ! f->empty() && f->back().getTerminator() == 0 )
- {
- BranchInst* branch = new BranchInst(bb);
- f->back().getInstList().push_back( branch );
- }
- f->getBasicBlockList().push_back( bb );
-}
-
-
-//===----------------------------------------------------------------------===//
-// handleXXX - Handle semantics of parser productions
-//===----------------------------------------------------------------------===//
-
-Module*
-StackerCompiler::handle_module_start( )
-{
- // Return the newly created module
- return TheModule;
-}
-
-Module*
-StackerCompiler::handle_module_end( Module* mod )
-{
- // Return the module.
- return mod;
-}
-
-Module*
-StackerCompiler::handle_definition_list_start()
-{
- return TheModule;
-}
-
-Module*
-StackerCompiler::handle_definition_list_end( Module* mod, Function* definition )
-{
- if ( ! definition->empty() )
- {
- BasicBlock& last_block = definition->back();
- if ( last_block.getTerminator() == 0 )
- {
- last_block.getInstList().push_back( new ReturnInst() );
- }
- }
- // Insert the definition into the module
- mod->getFunctionList().push_back( definition );
-
- // Bump our (sample) statistic.
- ++NumDefinitions;
- return mod;
-}
-
-Function*
-StackerCompiler::handle_main_definition( Function* func )
-{
- // Set the name of the function defined as the Stacker main
- // This will get called by the "main" that is defined in
- // the runtime library.
- func->setName( "_MAIN_");
-
- // Turn "_stack_" into an initialized variable since this is the main
- // module. This causes it to not be "external" but defined in this module.
- TheStack->setInitializer( Constant::getNullValue(stack_type) );
- TheStack->setLinkage( GlobalValue::LinkOnceLinkage );
-
- // Turn "_index_" into an intialized variable for the same reason.
- TheIndex->setInitializer( Constant::getNullValue(Type::Int64Ty) );
- TheIndex->setLinkage( GlobalValue::LinkOnceLinkage );
-
- return func;
-}
-
-Function*
-StackerCompiler::handle_forward( char * name )
-{
- // Just create a placeholder function
- Function* the_function = new Function (
- DefinitionType,
- GlobalValue::ExternalLinkage,
- name );
- assert( the_function->isExternal() );
-
- free( name );
- return the_function;
-}
-
-Function*
-StackerCompiler::handle_definition( char * name, Function* f )
-{
- // Look up the function name in the module to see if it was forward
- // declared.
-#if 0
- Function* existing_function = TheModule->getNamedFunction( name );
-
- // If the function already exists...
- if ( existing_function )
- {
- // Just get rid of the placeholder
- existing_function->dropAllReferences();
- delete existing_function;
- }
-#endif
-
- // Just set the name of the function now that we know what it is.
- f->setName( name );
-
- free( name );
-
- return f;
-}
-
-Function*
-StackerCompiler::handle_word_list_start()
-{
- TheFunction = new Function(DefinitionType, GlobalValue::ExternalLinkage);
- return TheFunction;
-}
-
-Function*
-StackerCompiler::handle_word_list_end( Function* f, BasicBlock* bb )
-{
- add_block( f, bb );
- return f;
-}
-
-BasicBlock*
-StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
-{
- // Create a basic block for the preamble
- BasicBlock* bb = new BasicBlock((echo?"if":""));
-
- // Get the condition value
- LoadInst* cond = cast<LoadInst>( pop_integer(bb) );
-
- // Compare the condition against 0
- ICmpInst* cond_inst = new ICmpInst( ICmpInst::ICMP_NE, cond,
- ConstantInt::get( Type::Int64Ty, 0) );
- bb->getInstList().push_back( cond_inst );
-
- // Create an exit block
- BasicBlock* exit_bb = new BasicBlock((echo?"endif":""));
-
- // Create the true_block
- BasicBlock* true_bb = new BasicBlock((echo?"then":""));
-
- // Create the false_block
- BasicBlock* false_bb = 0;
- if ( ifFalse ) false_bb = new BasicBlock((echo?"else":""));
-
- // Create a branch on the ICmp
- BranchInst* br_inst = new BranchInst( true_bb,
- ( ifFalse ? false_bb : exit_bb ), cond_inst );
- bb->getInstList().push_back( br_inst );
-
- // Fill the true block
- std::vector<Value*> args;
- if ( Function* true_func = TheModule->getNamedFunction(ifTrue) )
- {
- true_bb->getInstList().push_back(
- new CallInst( true_func, args ) );
- true_bb->getInstList().push_back(
- new BranchInst( exit_bb ) );
- }
- else
- {
- ThrowException(std::string("Function '") + ifTrue +
- "' must be declared first.'");
- }
-
- free( ifTrue );
-
- // Fill the false block
- if ( false_bb )
- {
- if ( Function* false_func = TheModule->getNamedFunction(ifFalse) )
- {
- false_bb->getInstList().push_back(
- new CallInst( false_func, args ) );
- false_bb->getInstList().push_back(
- new BranchInst( exit_bb ) );
- }
- else
- {
- ThrowException(std::string("Function '") + ifFalse +
- "' must be declared first.'");
- }
- free( ifFalse );
- }
-
- // Add the blocks to the function
- add_block( TheFunction, bb );
- add_block( TheFunction, true_bb );
- if ( false_bb ) add_block( TheFunction, false_bb );
-
- return exit_bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_while( char* todo )
-{
-
- // Create a basic block for the loop test
- BasicBlock* test = new BasicBlock((echo?"while":""));
-
- // Create an exit block
- BasicBlock* exit = new BasicBlock((echo?"end":""));
-
- // Create a loop body block
- BasicBlock* body = new BasicBlock((echo?"do":""));
-
- // Create a root node
- BasicBlock* bb = new BasicBlock((echo?"root":""));
- BranchInst* root_br_inst = new BranchInst( test );
- bb->getInstList().push_back( root_br_inst );
-
- // Examine the condition value
- LoadInst* cond = cast<LoadInst>( stack_top(test) );
-
- // Compare the condition against 0
- ICmpInst* cond_inst = new ICmpInst(
- ICmpInst::ICMP_NE, cond, ConstantInt::get( Type::Int64Ty, 0));
- test->getInstList().push_back( cond_inst );
-
- // Add the branch instruction
- BranchInst* br_inst = new BranchInst( body, exit, cond_inst );
- test->getInstList().push_back( br_inst );
-
- // Fill in the body
- std::vector<Value*> args;
- if ( Function* body_func = TheModule->getNamedFunction(todo) )
- {
- body->getInstList().push_back( new CallInst( body_func, args ) );
- body->getInstList().push_back( new BranchInst( test ) );
- }
- else
- {
- ThrowException(std::string("Function '") + todo +
- "' must be declared first.'");
- }
-
- free( todo );
-
- // Add the blocks
- add_block( TheFunction, bb );
- add_block( TheFunction, test );
- add_block( TheFunction, body );
-
- return exit;
-}
-
-BasicBlock*
-StackerCompiler::handle_identifier( char * name )
-{
- Function* func = TheModule->getNamedFunction( name );
- BasicBlock* bb = new BasicBlock((echo?"call":""));
- if ( func )
- {
- CallInst* call_def = new CallInst( func , no_arguments );
- bb->getInstList().push_back( call_def );
- }
- else
- {
- ThrowException(std::string("Definition '") + name +
- "' must be defined before it can be used.");
- }
-
- free( name );
- return bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_string( char * value )
-{
- // Create a new basic block for the push operation
- BasicBlock* bb = new BasicBlock((echo?"string":""));
-
- // Push the string onto the stack
- push_string(bb, value);
-
- // Free the strdup'd string
- free( value );
-
- return bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_integer( const int64_t value )
-{
- // Create a new basic block for the push operation
- BasicBlock* bb = new BasicBlock((echo?"int":""));
-
- // Push the integer onto the stack
- push_integer(bb, value );
-
- return bb;
-}
-
-BasicBlock*
-StackerCompiler::handle_word( int tkn )
-{
- // Create a new basic block to hold the instruction(s)
- BasicBlock* bb = new BasicBlock();
-
- /* Fill the basic block with the appropriate instructions */
- switch ( tkn )
- {
- case DUMP : // Dump the stack (debugging aid)
- {
- if (echo) bb->setName("DUMP");
- Constant * f = TheModule->getOrInsertFunction(
- "_stacker_dump_stack_", DefinitionType);
- std::vector<Value*> args;
- bb->getInstList().push_back( new CallInst( f, args ) );
- break;
- }
-
- // Logical Operations
- case TRUETOK : // -- -1
- {
- if (echo) bb->setName("TRUE");
- push_integer(bb,-1);
- break;
- }
- case FALSETOK : // -- 0
- {
- if (echo) bb->setName("FALSE");
- push_integer(bb,0);
- break;
- }
- case LESS : // w1 w2 -- w2<w1
- {
- if (echo) bb->setName("LESS");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- ICmpInst* cond_inst =
- new ICmpInst( ICmpInst::ICMP_SLT, op1, op2 );
- bb->getInstList().push_back( cond_inst );
- push_value( bb, cond_inst );
- break;
- }
- case MORE : // w1 w2 -- w2>w1
- {
- if (echo) bb->setName("MORE");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- ICmpInst* cond_inst =
- new ICmpInst( ICmpInst::ICMP_SGT, op1, op2 );
- bb->getInstList().push_back( cond_inst );
- push_value( bb, cond_inst );
- break;
- }
- case LESS_EQUAL : // w1 w2 -- w2<=w1
- {
- if (echo) bb->setName("LE");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- ICmpInst* cond_inst =
- new ICmpInst( ICmpInst::ICMP_SLE, op1, op2 );
- bb->getInstList().push_back( cond_inst );
- push_value( bb, cond_inst );
- break;
- }
- case MORE_EQUAL : // w1 w2 -- w2>=w1
- {
- if (echo) bb->setName("GE");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- ICmpInst* cond_inst =
- new ICmpInst( ICmpInst::ICMP_SGE, op1, op2 );
- bb->getInstList().push_back( cond_inst );
- push_value( bb, cond_inst );
- break;
- }
- case NOT_EQUAL : // w1 w2 -- w2!=w1
- {
- if (echo) bb->setName("NE");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- ICmpInst* cond_inst =
- new ICmpInst( ICmpInst::ICMP_NE, op1, op2 );
- bb->getInstList().push_back( cond_inst );
- push_value( bb, cond_inst );
- break;
- }
- case EQUAL : // w1 w2 -- w1==w2
- {
- if (echo) bb->setName("EQ");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- ICmpInst* cond_inst =
- new ICmpInst( ICmpInst::ICMP_EQ, op1, op2 );
- bb->getInstList().push_back( cond_inst );
- push_value( bb, cond_inst );
- break;
- }
-
- // Arithmetic Operations
- case PLUS : // w1 w2 -- w2+w1
- {
- if (echo) bb->setName("ADD");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* addop =
- BinaryOperator::create( Instruction::Add, op1, op2);
- bb->getInstList().push_back( addop );
- push_value( bb, addop );
- break;
- }
- case MINUS : // w1 w2 -- w2-w1
- {
- if (echo) bb->setName("SUB");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* subop =
- BinaryOperator::create( Instruction::Sub, op1, op2);
- bb->getInstList().push_back( subop );
- push_value( bb, subop );
- break;
- }
- case INCR : // w1 -- w1+1
- {
- if (echo) bb->setName("INCR");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* addop =
- BinaryOperator::create( Instruction::Add, op1, One );
- bb->getInstList().push_back( addop );
- push_value( bb, addop );
- break;
- }
- case DECR : // w1 -- w1-1
- {
- if (echo) bb->setName("DECR");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* subop = BinaryOperator::create( Instruction::Sub, op1,
- ConstantInt::get( Type::Int64Ty, 1 ) );
- bb->getInstList().push_back( subop );
- push_value( bb, subop );
- break;
- }
- case MULT : // w1 w2 -- w2*w1
- {
- if (echo) bb->setName("MUL");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* multop =
- BinaryOperator::create( Instruction::Mul, op1, op2);
- bb->getInstList().push_back( multop );
- push_value( bb, multop );
- break;
- }
- case DIV :// w1 w2 -- w2/w1
- {
- if (echo) bb->setName("DIV");
- LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* divop =
- BinaryOperator::create( Instruction::SDiv, op1, op2);
- bb->getInstList().push_back( divop );
- push_value( bb, divop );
- break;
- }
- case MODULUS : // w1 w2 -- w2%w1
- {
- if (echo) bb->setName("MOD");