diff options
Diffstat (limited to 'projects/Stacker/lib/compiler/StackerCompiler.cpp')
-rw-r--r-- | projects/Stacker/lib/compiler/StackerCompiler.cpp | 1806 |
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"); |