mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	This patch converts the old SHR instruction into two instructions, AShr (Arithmetic) and LShr (Logical). The Shr instructions now are not dependent on the sign of their operands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31542 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			1805 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1805 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- 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/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;
 | |
| 
 | |
| 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)
 | |
|     , 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::LongTy, 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::LongTy,
 | |
|             /*isConstant=*/false,
 | |
|             /*Linkage=*/GlobalValue::LinkOnceLinkage,
 | |
|             /*initializer=*/ Constant::getNullValue(Type::LongTy),
 | |
|             /*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);
 | |
| 
 | |
|         Constant* 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
 | |
|         );
 | |
| 
 | |
|         Constant* 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
 | |
|         );
 | |
| 
 | |
|         Constant* 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
 | |
|         );
 | |
| 
 | |
|         Constant* 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
 | |
|         );
 | |
| 
 | |
|         Constant* 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
 | |
|         );
 | |
| 
 | |
|         Constant* 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 );
 | |
| 
 | |
|         // 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 = 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 a long .. hopefully it works
 | |
|     CastInst* cast_inst = new CastInst( val, Type::LongTy );
 | |
|     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::LongTy, 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
 | |
|     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 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
 | |
|     // 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::LongTy) );
 | |
|     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
 | |
|     SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond,
 | |
|         ConstantInt::get( Type::LongTy, 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 );
 | |
| 
 | |
|     // Examine the condition value
 | |
|     LoadInst* cond = cast<LoadInst>( stack_top(test) );
 | |
| 
 | |
|     // Compare the condition against 0
 | |
|     SetCondInst* cond_inst = new SetCondInst(
 | |
|         Instruction::SetNE, cond, ConstantInt::get( Type::LongTy, 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");
 | |
|         Function* 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));
 | |
|         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, 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::LongTy, 1 ) );
 | |
|         bb->getInstList().push_back( subop );
 | |
|         push_value( bb, subop );
 | |
|         break;
 | |
|     }
 | |
|     case MULT : // w1 w2 -- w2*w1
 | |
|     {
 | |
|         if (echo) bb->setName("MUL");
 | |
|         LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
 | |
|         LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
 | |
|         BinaryOperator* multop =
 | |
|             BinaryOperator::create( Instruction::Mul, op1, op2);
 | |
|         bb->getInstList().push_back( multop );
 | |
|         push_value( bb, multop );
 | |
|         break;
 | |
|     }
 | |
|     case DIV :// w1 w2 -- w2/w1
 | |
|     {
 | |
|         if (echo) bb->setName("DIV");
 | |
|         LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
 | |
|         LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
 | |
|         BinaryOperator* divop =
 | |
|             BinaryOperator::create( Instruction::SDiv, op1, op2);
 | |
|         bb->getInstList().push_back( divop );
 | |
|         push_value( bb, divop );
 | |
|         break;
 | |
|     }
 | |
|     case MODULUS : // w1 w2 -- w2%w1
 | |
|     {
 | |
|         if (echo) bb->setName("MOD");
 | |
|         LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
 | |
|         LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
 | |
|         BinaryOperator* divop =
 | |
|             BinaryOperator::create( Instruction::SRem, op1, op2);
 | |
|         bb->getInstList().push_back( divop );
 | |
|         push_value( bb, divop );
 | |
|         break;
 | |
|     }
 | |
|     case STAR_SLASH : // w1 w2 w3 -- (w3*w2)/w1
 | |
|     {
 | |
|         if (echo) bb->setName("STAR_SLASH");
 | |
|         // Get the operands
 | |
|         LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
 | |
|         LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
 | |
|         LoadInst* op3 = cast<LoadInst>(pop_integer(bb));
 | |
| 
 | |
|         // Multiply the first two
 | |
|         BinaryOperator* multop =
 | |
|             BinaryOperator::create( Instruction::Mul, op1, op2);
 | |
|         bb->getInstList().push_back( multop );
 | |
| 
 | |
|         // Divide by the third operand
 | |
|         BinaryOperator* divop =
 | |
|             BinaryOperator::create( Instruction::SDiv, multop, op3);
 | |
|         bb->getInstList().push_back( divop );
 | |
| 
 | |
|         // Push the result
 | |
|         push_value( bb, divop );
 | |
| 
 | |
|         break;
 | |
|     }
 | |
|     case NEGATE : // w1 -- -w1
 | |
|     {
 | |
|         if (echo) bb->setName("NEG");
 | |
|         LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
 | |
|         // APPARENTLY, the following doesn't work:
 | |
|         // BinaryOperator* negop = BinaryOperator::createNeg( op1 );
 | |
|         // bb->getInstList().push_back( negop );
 | |
|         // So we'll multiply by -1 (ugh)
 | |
|         BinaryOperator* multop = BinaryOperator::create( Instruction::Mul, op1,
 | |
|             ConstantInt::get( Type::LongTy, -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, Zero );
 | |
|         bb->getInstList().push_back( cond_inst );
 | |
| 
 | |
|         // Create a block for storing the result
 | |
|         BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
 | |
| 
 | |
|         // Create a block for making it a positive value
 | |
|         BasicBlock* pos_bb = new BasicBlock((echo?"neg":""));
 | |
| 
 | |
|         // Create the branch on the 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::AShr, op2, castop );
 | |
|         bb->getInstList().push_back( shrop );
 | |
|         push_value( bb, shrop );
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     // Stack Manipulation Operations
 | |
|     case DROP:          // w --
 | |
|     {
 | |
|         if (echo) bb->setName("DROP");
 | |
|         decr_stack_index(bb, One);
 | |
|         break;
 | |
|     }
 | |
|     case DROP2: // w1 w2 --
 | |
|     {
 | |
|         if (echo) bb->setName("DROP2");
 | |
|         decr_stack_index( bb, Two );
 | |
|         break;
 | |
|     }
 | |
|     case NIP:   // w1 w2 -- w2
 | |
|     {
 | |
|         if (echo) bb->setName("NIP");
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
 | |
|         decr_stack_index( bb  );
 | |
|         replace_top( bb, w2 );
 | |
|         break;
 | |
|     }
 | |
|     case NIP2:  // w1 w2 w3 w4 -- w3 w4
 | |
|     {
 | |
|         if (echo) bb->setName("NIP2");
 | |
|         LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         decr_stack_index( bb, Two );
 | |
|         replace_top( bb, w4 );
 | |
|         replace_top( bb, w3, One );
 | |
|         break;
 | |
|     }
 | |
|     case DUP:   // w -- w w
 | |
|     {
 | |
|         if (echo) bb->setName("DUP");
 | |
|         LoadInst* w = cast<LoadInst>( stack_top( bb ) );
 | |
|         push_value( bb, w );
 | |
|         break;
 | |
|     }
 | |
|     case DUP2:  // w1 w2 -- w1 w2 w1 w2
 | |
|     {
 | |
|         if (echo) bb->setName("DUP2");
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top(bb) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top(bb, One ) );
 | |
|         incr_stack_index( bb, Two );
 | |
|         replace_top( bb, w1, One );
 | |
|         replace_top( bb, w2 );
 | |
|         break;
 | |
|     }
 | |
|     case SWAP:  // w1 w2 -- w2 w1
 | |
|     {
 | |
|         if (echo) bb->setName("SWAP");
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         replace_top( bb, w1 );
 | |
|         replace_top( bb, w2, One );
 | |
|         break;
 | |
|     }
 | |
|     case SWAP2: // w1 w2 w3 w4 -- w3 w4 w1 w2
 | |
|     {
 | |
|         if (echo) bb->setName("SWAP2");
 | |
|         LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three ) );
 | |
|         replace_top( bb, w2 );
 | |
|         replace_top( bb, w1, One );
 | |
|         replace_top( bb, w4, Two );
 | |
|         replace_top( bb, w3, Three );
 | |
|         break;
 | |
|     }
 | |
|     case OVER:  // w1 w2 -- w1 w2 w1
 | |
|     {
 | |
|         if (echo) bb->setName("OVER");
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         push_value( bb, w1 );
 | |
|         break;
 | |
|     }
 | |
|     case OVER2: // w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2
 | |
|     {
 | |
|         if (echo) bb->setName("OVER2");
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three ) );
 | |
|         incr_stack_index( bb, Two );
 | |
|         replace_top( bb, w2 );
 | |
|         replace_top( bb, w1, One );
 | |
|         break;
 | |
|     }
 | |
|     case ROT:   // w1 w2 w3 -- w2 w3 w1
 | |
|     {
 | |
|         if (echo) bb->setName("ROT");
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         replace_top( bb, w1 );
 | |
|         replace_top( bb, w3, One );
 | |
|         replace_top( bb, w2, Two );
 | |
|         break;
 | |
|     }
 | |
|     case ROT2:  // w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2
 | |
|     {
 | |
|         if (echo) bb->setName("ROT2");
 | |
|         LoadInst* w6 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w5 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         LoadInst* w4 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb, Three) );
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, Four ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Five ) );
 | |
|         replace_top( bb, w2 );
 | |
|         replace_top( bb, w1, One );
 | |
|         replace_top( bb, w6, Two );
 | |
|         replace_top( bb, w5, Three );
 | |
|         replace_top( bb, w4, Four );
 | |
|         replace_top( bb, w3, Five );
 | |
|         break;
 | |
|     }
 | |
|     case RROT:  // w1 w2 w3 -- w3 w1 w2
 | |
|     {
 | |
|         if (echo) bb->setName("RROT2");
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         replace_top( bb, w2 );
 | |
|         replace_top( bb, w1, One );
 | |
|         replace_top( bb, w3, Two );
 | |
|         break;
 | |
|     }
 | |
|     case RROT2: // w1 w2 w3 w4 w5 w6 -- w5 w6 w1 w2 w3 w4
 | |
|     {
 | |
|         if (echo) bb->setName("RROT2");
 | |
|         LoadInst* w6 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w5 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         LoadInst* w4 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb, Three) );
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, Four ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Five ) );
 | |
|         replace_top( bb, w4 );
 | |
|         replace_top( bb, w3, One );
 | |
|         replace_top( bb, w2, Two );
 | |
|         replace_top( bb, w1, Three );
 | |
|         replace_top( bb, w6, Four );
 | |
|         replace_top( bb, w5, Five );
 | |
|         break;
 | |
|     }
 | |
|     case TUCK:  // w1 w2 -- w2 w1 w2
 | |
|     {
 | |
|         if (echo) bb->setName("TUCK");
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         incr_stack_index( bb );
 | |
|         replace_top( bb, w2 );
 | |
|         replace_top( bb, w1, One );
 | |
|         replace_top( bb, w2, Two );
 | |
|         break;
 | |
|     }
 | |
|     case TUCK2: // w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4
 | |
|     {
 | |
|         if (echo) bb->setName("TUCK2");
 | |
|         LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
 | |
|         LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
 | |
|         LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
 | |
|         LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three) );
 | |
|         incr_stack_index( bb, Two );
 | |
|         replace_top( bb, w4 );
 | |
|         replace_top( bb, w3, One );
 | |
|         replace_top( bb, w2, Two );
 | |
|         replace_top( bb, w1, Three );
 | |
|         replace_top( bb, w4, Four );
 | |
|         replace_top( bb, w3, Five );
 | |
|         break;
 | |
|     }
 | |
|     case ROLL:  // x0 x1 .. xn n -- x1 .. xn x0
 | |
|     {
 | |
|         /// THIS OEPRATOR IS OMITTED PURPOSEFULLY AND IS LEFT TO THE
 | |
|         /// READER AS AN EXERCISE. THIS IS ONE OF THE MORE COMPLICATED
 | |
|         /// OPERATORS. IF YOU CAN GET THIS ONE RIGHT, YOU COMPLETELY
 | |
|         /// UNDERSTAND HOW BOTH LLVM AND STACKER WOR.
 | |
|         /// HINT: LOOK AT PICK AND SELECT. ROLL IS SIMILAR.
 | |
|         if (echo) bb->setName("ROLL");
 | |
|         break;
 | |
|     }
 | |
|     case PICK:  // x0 ... Xn n -- x0 ... Xn x0
 | |
|     {
 | |
|         if (echo) bb->setName("PICK");
 | |
|         LoadInst* n = cast<LoadInst>( stack_top( bb ) );
 | |
|         BinaryOperator* addop =
 | |
|             BinaryOperator::create( Instruction::Add, n, One );
 | |
|         bb->getInstList().push_back( addop );
 | |
|         LoadInst* x0 = cast<LoadInst>( stack_top( bb, addop ) );
 | |
|         replace_top( bb, x0 );
 | |
|         break;
 | |
|     }
 | |
|     case SELECT:        // m n X0..Xm Xm+1 .. Xn -- Xm
 | |
|     {
 | |
|         if (echo) bb->setName("SELECT");
 | |
|         LoadInst* m = cast<LoadInst>( stack_top(bb) );
 | |
|         LoadInst* n = cast<LoadInst>( stack_top(bb, One) );
 | |
|         BinaryOperator* index =
 | |
|             BinaryOperator::create( Instruction::Add, m, One );
 | |
|         bb->getInstList().push_back( index );
 | |
|         LoadInst* Xm = cast<LoadInst>( stack_top(bb, index ) );
 | |
|         BinaryOperator* n_plus_1 =
 | |
|             BinaryOperator::create( Instruction::Add, n, One );
 | |
|         bb->getInstList().push_back( n_plus_1 );
 | |
|         decr_stack_index( bb, n_plus_1 );
 | |
|         replace_top( bb, Xm );
 | |
|         break;
 | |
|     }
 | |
|     case MALLOC : // n -- p
 | |
|     {
 | |
|         if (echo) bb->setName("MALLOC");
 | |
|         // Get the number of bytes to mallocate
 | |
|         LoadInst* op1 = cast<LoadInst>( pop_integer(bb) );
 | |
| 
 | |
|         // Make sure its a UIntTy
 | |
|         CastInst* caster = 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));
 | |
| 
 | |
|         // Cast down to an integer
 | |
|         CastInst* caster = new CastInst( op1, Type::IntTy );
 | |
|         bb->getInstList().push_back( caster );
 | |
| 
 | |
|         // Call exit(3)
 | |
|         std::vector<Value*> params;
 | |
|         params.push_back(caster);
 | |
|         CallInst* call_inst = new CallInst( TheExit, params );
 | |
|         bb->getInstList().push_back( call_inst );
 | |
|         break;
 | |
|     }
 | |
|     case TAB :
 | |
|     {
 | |
|         if (echo) bb->setName("TAB");
 | |
|         // Get the format string for a character
 | |
|         std::vector<Value*> indexVec;
 | |
|         indexVec.push_back( Zero );
 | |
|         indexVec.push_back( Zero );
 | |
|         GetElementPtrInst* format_gep =
 | |
|             new GetElementPtrInst( ChrFormat, indexVec );
 | |
|         bb->getInstList().push_back( format_gep );
 | |
| 
 | |
|         // Get the character to print (a tab)
 | |
|         ConstantInt* newline = ConstantInt::get(Type::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 space)
 | |
|         ConstantInt* newline = ConstantInt::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)
 | |
|         ConstantInt* newline = ConstantInt::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;
 | |
| }
 |