//===-- 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
+// 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
+// Globasl - Global variables we use
//===----------------------------------------------------------------------===//
-#include <llvm/Analysis/Verifier.h>
-#include <llvm/iMemory.h>
-#include <llvm/iOperators.h>
-#include <llvm/iOther.h>
-#include <llvm/iTerminators.h>
-#include <Support/Statistic.h>
+#include "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>
, Three(0)
, Four(0)
, Five(0)
- , IZero(0)
- , IOne(0)
- , ITwo(0)
, no_arguments()
, echo(false)
, stack_size(256)
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
+ // 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;
StackerCompiler::compile(
const std::string& filename,
bool should_echo,
+ unsigned optLevel,
size_t the_stack_size
)
{
FILE *F = stdin;
///
- if (filename != "-")
+ if (filename != "-")
{
F = fopen(filename.c_str(), "r");
if (F == 0)
{
- throw ParseException(filename,
+ throw ParseException(filename,
"Could not open file '" + filename + "'");
}
}
Module *Result;
- try
+ try
{
// Create the module we'll return
TheModule = new Module( CurFilename );
- // Create a type to represent the stack. This is the same as the LLVM
- // Assembly type [ 256 x int ]
- stack_type = ArrayType::get( Type::IntTy, stack_size );
+ // 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
+ // Create a global variable for the stack. Note the use of appending
+ // linkage linkage so that multiple modules will make the stack larger.
+ // Also note that the last argument causes the global to be inserted
// automatically into the module.
- TheStack = new GlobalVariable(
- /*type=*/ stack_type,
- /*isConstant=*/ false,
- /*Linkage=*/ GlobalValue::AppendingLinkage,
- /*initializer=*/0,
+ TheStack = new GlobalVariable(
+ /*type=*/ stack_type,
+ /*isConstant=*/ false,
+ /*Linkage=*/ GlobalValue::LinkOnceLinkage,
+ /*initializer=*/ Constant::getNullValue(stack_type),
/*name=*/ "_stack_",
- /*parent=*/ TheModule
+ /*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
+ // 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,
+ TheIndex = new GlobalVariable(
+ /*type=*/Type::LongTy,
/*isConstant=*/false,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/0,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/ Constant::getNullValue(Type::LongTy),
/*name=*/"_index_",
/*parent=*/TheModule
);
- // Create a function prototype for definitions. No parameters, no
+ // 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* printf_type =
FunctionType::get( Type::IntTy, params, true );
- ThePrintf = new Function(
+ ThePrintf = new Function(
printf_type, GlobalValue::ExternalLinkage, "printf", TheModule);
// Create a function for scanf(3)
- TheScanf = new Function(
+ 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* exit_type =
FunctionType::get( Type::VoidTy, params, false );
- TheExit = new Function(
+ TheExit = new Function(
exit_type, GlobalValue::ExternalLinkage, "exit", TheModule);
- ConstantArray* str_format = ConstantArray::get("%s");
- StrFormat = new GlobalVariable(
+ Constant* str_format = ConstantArray::get("%s");
+ StrFormat = new GlobalVariable(
/*type=*/ArrayType::get( Type::SByteTy, 3 ),
/*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/str_format,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/str_format,
/*name=*/"_str_format_",
/*parent=*/TheModule
);
- ConstantArray* in_str_format = ConstantArray::get(" %as");
- InStrFormat = new GlobalVariable(
+ 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,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/in_str_format,
/*name=*/"_in_str_format_",
/*parent=*/TheModule
);
- ConstantArray* num_format = ConstantArray::get("%d");
- NumFormat = new GlobalVariable(
+ Constant* num_format = ConstantArray::get("%d");
+ NumFormat = new GlobalVariable(
/*type=*/ArrayType::get( Type::SByteTy, 3 ),
/*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/num_format,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/num_format,
/*name=*/"_num_format_",
/*parent=*/TheModule
);
- ConstantArray* in_num_format = ConstantArray::get(" %d");
- InNumFormat = new GlobalVariable(
+ 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,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/in_num_format,
/*name=*/"_in_num_format_",
/*parent=*/TheModule
);
- ConstantArray* chr_format = ConstantArray::get("%c");
- ChrFormat = new GlobalVariable(
+ Constant* chr_format = ConstantArray::get("%c");
+ ChrFormat = new GlobalVariable(
/*type=*/ArrayType::get( Type::SByteTy, 3 ),
/*isConstant=*/true,
- /*Linkage=*/GlobalValue::LinkOnceLinkage,
- /*initializer=*/chr_format,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/chr_format,
/*name=*/"_chr_format_",
/*parent=*/TheModule
);
- ConstantArray* in_chr_format = ConstantArray::get(" %c");
- InChrFormat = new GlobalVariable(
+ 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,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/in_chr_format,
/*name=*/"_in_chr_format_",
/*parent=*/TheModule
);
Three = ConstantInt::get( Type::LongTy, 3 );
Four = ConstantInt::get( Type::LongTy, 4 );
Five = ConstantInt::get( Type::LongTy, 5 );
- IZero = ConstantInt::get( Type::IntTy, 0 );
- IOne = ConstantInt::get( Type::IntTy, 1 );
- ITwo = ConstantInt::get( Type::IntTy, 2 );
// Reset the current line number
- Stackerlineno = 1;
+ Stackerlineno = 1;
// Reset the parser's input to F
Stackerin = F; // Set the input file.
// Let the parse know about this instance
TheInstance = this;
- // Parse the file. The parser (see StackParser.y) will call back to
- // the StackCompiler via the "handle*" methods
- Stackerparse();
+ // 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("stkrc",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
+ 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;
}
if ( ival == 0 ) ival = One;
CastInst* caster = new CastInst( ival, Type::LongTy );
bb->getInstList().push_back( caster );
- BinaryOperator* addop = BinaryOperator::create( Instruction::Add,
+ BinaryOperator* addop = BinaryOperator::create( Instruction::Add,
loadop, caster);
bb->getInstList().push_back( addop );
if ( ival == 0 ) ival = One;
CastInst* caster = new CastInst( ival, Type::LongTy );
bb->getInstList().push_back( caster );
- BinaryOperator* subop = BinaryOperator::create( Instruction::Sub,
+ BinaryOperator* subop = BinaryOperator::create( Instruction::Sub,
loadop, caster);
bb->getInstList().push_back( subop );
Instruction*
StackerCompiler::get_stack_pointer( BasicBlock* bb, Value* index = 0 )
{
- // Load the value of the Stack Index
+ // Load the value of the Stack Index
LoadInst* loadop = new LoadInst( TheIndex );
bb->getInstList().push_back( loadop );
{
CastInst* caster = new CastInst( index, Type::LongTy );
bb->getInstList().push_back( caster );
- BinaryOperator* subop = BinaryOperator::create(
+ BinaryOperator* subop = BinaryOperator::create(
Instruction::Sub, loadop, caster );
bb->getInstList().push_back( subop );
indexVec.push_back(subop);
Instruction*
StackerCompiler::push_value( BasicBlock* bb, Value* val )
{
- // Get location of
+ // Get location of
incr_stack_index(bb);
// Get the stack pointer
- GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
get_stack_pointer( bb ) );
- // Cast the value to an integer .. hopefully it works
- CastInst* cast_inst = new CastInst( val, Type::IntTy );
+ // 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
}
Instruction*
-StackerCompiler::push_integer(BasicBlock* bb, int32_t value )
+StackerCompiler::push_integer(BasicBlock* bb, int64_t value )
{
// Just push a constant integer value
- return push_value( bb, ConstantSInt::get( Type::IntTy, value ) );
+ return push_value( bb, ConstantSInt::get( Type::LongTy, value ) );
}
Instruction*
// Get length of the string
size_t len = strlen( value );
- // Create a type for the string constant. Length is +1 for
+ // Create a type for the string constant. Length is +1 for
// the terminating 0.
ArrayType* char_array = ArrayType::get( Type::SByteTy, len + 1 );
// Create an initializer for the value
- ConstantArray* initVal = ConstantArray::get( value );
+ 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,
+ GlobalVariable* strconst = new GlobalVariable(
+ char_array,
+ /*isConstant=*/true,
+ GlobalValue::InternalLinkage,
/*initializer=*/initVal,
"",
TheModule
// 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 TheModule;
}
-Module*
+Module*
StackerCompiler::handle_module_end( Module* mod )
{
// Return the module.
return TheModule;
}
-Module*
+Module*
StackerCompiler::handle_definition_list_end( Module* mod, Function* definition )
{
if ( ! definition->empty() )
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_");
- // Create the actual main for the runtime system.
- //std::vector<const Type*> params; // No parameters
- //FunctionType* main_type = FunctionType::get( Type::IntTy, params, false );
- Function* SystemMain = new Function(
- DefinitionType,
- GlobalValue::ExternalLinkage,
- "main", TheModule);
-
- // Create a basic block that just calls the STACKERMAIN function. Note
- // that the basic block is automatically inserted into the end of SystemMain
- BasicBlock* bb = new BasicBlock( (echo?"main":"a"), SystemMain ) ;
- bb->getInstList().push_back( new CallInst( func, no_arguments) );
- bb->getInstList().push_back( new ReturnInst() );
-
// Turn "_stack_" into an initialized variable since this is the main
// module. This causes it to not be "external" but defined in this module.
TheStack->setInitializer( Constant::getNullValue(stack_type) );
+ 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*
+Function*
StackerCompiler::handle_forward( char * name )
{
// Just create a placeholder function
- Function* the_function = new Function (
- DefinitionType,
- GlobalValue::ExternalLinkage,
- name );
+ Function* the_function = new Function (
+ DefinitionType,
+ GlobalValue::ExternalLinkage,
+ name );
assert( the_function->isExternal() );
free( name );
return the_function;
}
-Function*
+Function*
StackerCompiler::handle_definition( char * name, Function* f )
{
// Look up the function name in the module to see if it was forward
return f;
}
-BasicBlock*
+BasicBlock*
StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
{
// Create a basic block for the preamble
// Get the condition value
LoadInst* cond = cast<LoadInst>( pop_integer(bb) );
- // Compare the condition against 0
- SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond,
- ConstantSInt::get( Type::IntTy, 0) );
+ // Compare the condition against 0
+ SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond,
+ ConstantSInt::get( Type::LongTy, 0) );
bb->getInstList().push_back( cond_inst );
// Create an exit block
if ( ifFalse ) false_bb = new BasicBlock((echo?"else":""));
// Create a branch on the SetCond
- BranchInst* br_inst = new BranchInst( true_bb,
+ BranchInst* br_inst = new BranchInst( true_bb,
( ifFalse ? false_bb : exit_bb ), cond_inst );
bb->getInstList().push_back( br_inst );
- // Fill the true block
+ // Fill the true block
std::vector<Value*> args;
if ( Function* true_func = TheModule->getNamedFunction(ifTrue) )
{
- true_bb->getInstList().push_back(
+ true_bb->getInstList().push_back(
new CallInst( true_func, args ) );
- true_bb->getInstList().push_back(
+ true_bb->getInstList().push_back(
new BranchInst( exit_bb ) );
}
else
{
- ThrowException(std::string("Function '") + ifTrue +
+ ThrowException(std::string("Function '") + ifTrue +
"' must be declared first.'");
}
{
if ( Function* false_func = TheModule->getNamedFunction(ifFalse) )
{
- false_bb->getInstList().push_back(
+ false_bb->getInstList().push_back(
new CallInst( false_func, args ) );
- false_bb->getInstList().push_back(
+ false_bb->getInstList().push_back(
new BranchInst( exit_bb ) );
}
else
{
- ThrowException(std::string("Function '") + ifFalse +
+ ThrowException(std::string("Function '") + ifFalse +
"' must be declared first.'");
}
free( ifFalse );
return exit_bb;
}
-BasicBlock*
+BasicBlock*
StackerCompiler::handle_while( char* todo )
{
// Pop the condition value
LoadInst* cond = cast<LoadInst>( stack_top(test) );
- // Compare the condition against 0
- SetCondInst* cond_inst = new SetCondInst(
- Instruction::SetNE, cond, ConstantSInt::get( Type::IntTy, 0) );
+ // Compare the condition against 0
+ SetCondInst* cond_inst = new SetCondInst(
+ Instruction::SetNE, cond, ConstantSInt::get( Type::LongTy, 0) );
test->getInstList().push_back( cond_inst );
// Add the branch instruction
}
else
{
- ThrowException(std::string("Function '") + todo +
+ ThrowException(std::string("Function '") + todo +
"' must be declared first.'");
}
return exit;
}
-BasicBlock*
+BasicBlock*
StackerCompiler::handle_identifier( char * name )
{
Function* func = TheModule->getNamedFunction( name );
}
else
{
- ThrowException(std::string("Definition '") + name +
+ ThrowException(std::string("Definition '") + name +
"' must be defined before it can be used.");
}
return bb;
}
-BasicBlock*
+BasicBlock*
StackerCompiler::handle_string( char * value )
{
// Create a new basic block for the push operation
return bb;
}
-BasicBlock*
-StackerCompiler::handle_integer( const int32_t value )
+BasicBlock*
+StackerCompiler::handle_integer( const int64_t value )
{
// Create a new basic block for the push operation
BasicBlock* bb = new BasicBlock((echo?"int":""));
return bb;
}
-BasicBlock*
+BasicBlock*
StackerCompiler::handle_word( int tkn )
{
// Create a new basic block to hold the instruction(s)
}
// Logical Operations
- case TRUE : // -- -1
+ case TRUETOK : // -- -1
{
if (echo) bb->setName("TRUE");
- push_integer(bb,-1);
+ push_integer(bb,-1);
break;
}
- case FALSE : // -- 0
+ case FALSETOK : // -- 0
{
if (echo) bb->setName("FALSE");
- push_integer(bb,0);
+ 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 =
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetLT, op1, op2 );
bb->getInstList().push_back( cond_inst );
push_value( bb, cond_inst );
if (echo) bb->setName("MORE");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- SetCondInst* cond_inst =
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetGT, op1, op2 );
bb->getInstList().push_back( cond_inst );
push_value( bb, cond_inst );
if (echo) bb->setName("LE");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- SetCondInst* cond_inst =
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetLE, op1, op2 );
bb->getInstList().push_back( cond_inst );
push_value( bb, cond_inst );
if (echo) bb->setName("GE");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- SetCondInst* cond_inst =
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetGE, op1, op2 );
bb->getInstList().push_back( cond_inst );
push_value( bb, cond_inst );
if (echo) bb->setName("NE");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- SetCondInst* cond_inst =
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetNE, op1, op2 );
bb->getInstList().push_back( cond_inst );
push_value( bb, cond_inst );
if (echo) bb->setName("EQ");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- SetCondInst* cond_inst =
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetEQ, op1, op2 );
bb->getInstList().push_back( cond_inst );
push_value( bb, cond_inst );
if (echo) bb->setName("ADD");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* addop =
+ BinaryOperator* addop =
BinaryOperator::create( Instruction::Add, op1, op2);
bb->getInstList().push_back( addop );
push_value( bb, addop );
if (echo) bb->setName("SUB");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* subop =
+ BinaryOperator* subop =
BinaryOperator::create( Instruction::Sub, op1, op2);
bb->getInstList().push_back( subop );
push_value( bb, subop );
{
if (echo) bb->setName("INCR");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* addop =
- BinaryOperator::create( Instruction::Add, op1, IOne );
+ BinaryOperator* addop =
+ BinaryOperator::create( Instruction::Add, op1, One );
bb->getInstList().push_back( addop );
push_value( bb, addop );
break;
if (echo) bb->setName("DECR");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
BinaryOperator* subop = BinaryOperator::create( Instruction::Sub, op1,
- ConstantSInt::get( Type::IntTy, 1 ) );
+ ConstantSInt::get( Type::LongTy, 1 ) );
bb->getInstList().push_back( subop );
push_value( bb, subop );
break;
if (echo) bb->setName("MUL");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* multop =
+ BinaryOperator* multop =
BinaryOperator::create( Instruction::Mul, op1, op2);
bb->getInstList().push_back( multop );
push_value( bb, multop );
if (echo) bb->setName("DIV");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* divop =
+ BinaryOperator* divop =
BinaryOperator::create( Instruction::Div, op1, op2);
bb->getInstList().push_back( divop );
push_value( bb, divop );
if (echo) bb->setName("MOD");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* divop =
+ BinaryOperator* divop =
BinaryOperator::create( Instruction::Rem, op1, op2);
bb->getInstList().push_back( divop );
push_value( bb, divop );
LoadInst* op3 = cast<LoadInst>(pop_integer(bb));
// Multiply the first two
- BinaryOperator* multop =
+ BinaryOperator* multop =
BinaryOperator::create( Instruction::Mul, op1, op2);
bb->getInstList().push_back( multop );
// Divide by the third operand
- BinaryOperator* divop =
+ BinaryOperator* divop =
BinaryOperator::create( Instruction::Div, multop, op3);
bb->getInstList().push_back( divop );
// bb->getInstList().push_back( negop );
// So we'll multiply by -1 (ugh)
BinaryOperator* multop = BinaryOperator::create( Instruction::Mul, op1,
- ConstantSInt::get( Type::IntTy, -1 ) );
+ ConstantSInt::get( Type::LongTy, -1 ) );
bb->getInstList().push_back( multop );
push_value( bb, multop );
break;
LoadInst* op1 = cast<LoadInst>(stack_top(bb));
// Determine if its negative
- SetCondInst* cond_inst =
- new SetCondInst( Instruction::SetLT, op1, IZero );
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetLT, op1, Zero );
bb->getInstList().push_back( cond_inst );
// Create a block for storing the result
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- // Compare them
- SetCondInst* cond_inst =
+ // 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 =
+ BranchInst* br_inst =
new BranchInst( op1_block, op2_block, cond_inst );
bb->getInstList().push_back( br_inst );
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- // Compare them
- SetCondInst* cond_inst =
+ // Compare them
+ SetCondInst* cond_inst =
new SetCondInst( Instruction::SetGT, op1, op2);
bb->getInstList().push_back( cond_inst );
op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
// Create a banch on the SetCond
- BranchInst* br_inst =
+ BranchInst* br_inst =
new BranchInst( op1_block, op2_block, cond_inst );
bb->getInstList().push_back( br_inst );
if (echo) bb->setName("AND");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* andop =
+ BinaryOperator* andop =
BinaryOperator::create( Instruction::And, op1, op2);
bb->getInstList().push_back( andop );
push_value( bb, andop );
if (echo) bb->setName("OR");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* orop =
+ BinaryOperator* orop =
BinaryOperator::create( Instruction::Or, op1, op2);
bb->getInstList().push_back( orop );
push_value( bb, orop );
if (echo) bb->setName("XOR");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
- BinaryOperator* xorop =
+ BinaryOperator* xorop =
BinaryOperator::create( Instruction::Xor, op1, op2);
bb->getInstList().push_back( xorop );
push_value( bb, xorop );
}
// Stack Manipulation Operations
- case DROP: // w --
+ case DROP: // w --
{
if (echo) bb->setName("DROP");
decr_stack_index(bb, One);
break;
}
- case DROP2: // w1 w2 --
+ case DROP2: // w1 w2 --
{
if (echo) bb->setName("DROP2");
decr_stack_index( bb, Two );
replace_top( bb, w2, Two );
break;
}
- case TUCK2: // w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4
+ case TUCK2: // w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4
{
if (echo) bb->setName("TUCK2");
LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
}
case ROLL: // x0 x1 .. xn n -- x1 .. xn x0
{
- /// THIS OEPRATOR IS OMITTED PURPOSEFULLY AND IS LEFT TO THE
+ /// 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.
+ /// UNDERSTAND HOW BOTH LLVM AND STACKER WOR.
/// HINT: LOOK AT PICK AND SELECT. ROLL IS SIMILAR.
if (echo) bb->setName("ROLL");
break;
{
if (echo) bb->setName("PICK");
LoadInst* n = cast<LoadInst>( stack_top( bb ) );
- BinaryOperator* addop =
- BinaryOperator::create( Instruction::Add, n, IOne );
+ 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 );
if (echo) bb->setName("SELECT");
LoadInst* m = cast<LoadInst>( stack_top(bb) );
LoadInst* n = cast<LoadInst>( stack_top(bb, One) );
- BinaryOperator* index =
- BinaryOperator::create( Instruction::Add, m, IOne );
+ 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, IOne );
+ 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 RECURSE :
+ case RECURSE :
{
if (echo) bb->setName("RECURSE");
std::vector<Value*> params;
bb->getInstList().push_back( call_inst );
break;
}
- case RETURN :
+ case RETURN :
{
if (echo) bb->setName("RETURN");
bb->getInstList().push_back( new ReturnInst() );
break;
}
- case EXIT :
+ 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(op1);
+ params.push_back(caster);
CallInst* call_inst = new CallInst( TheExit, params );
bb->getInstList().push_back( call_inst );
break;
std::vector<Value*> indexVec;
indexVec.push_back( Zero );
indexVec.push_back( Zero );
- GetElementPtrInst* format_gep =
+ GetElementPtrInst* format_gep =
new GetElementPtrInst( ChrFormat, indexVec );
bb->getInstList().push_back( format_gep );
- // Get the character to print (a newline)
- ConstantSInt* newline = ConstantSInt::get(Type::IntTy,
+ // Get the character to print (a tab)
+ ConstantSInt* newline = ConstantSInt::get(Type::IntTy,
static_cast<int>('\t'));
// Call printf
bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
break;
}
- case SPACE :
+ 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 =
+ GetElementPtrInst* format_gep =
new GetElementPtrInst( ChrFormat, indexVec );
bb->getInstList().push_back( format_gep );
- // Get the character to print (a newline)
- ConstantSInt* newline = ConstantSInt::get(Type::IntTy,
+ // Get the character to print (a space)
+ ConstantSInt* newline = ConstantSInt::get(Type::IntTy,
static_cast<int>(' '));
// Call printf
bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
break;
}
- case CR :
+ 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 =
+ GetElementPtrInst* format_gep =
new GetElementPtrInst( ChrFormat, indexVec );
bb->getInstList().push_back( format_gep );
// Get the character to print (a newline)
- ConstantSInt* newline = ConstantSInt::get(Type::IntTy,
+ ConstantSInt* newline = ConstantSInt::get(Type::IntTy,
static_cast<int>('\n'));
// Call printf
bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
break;
}
- case IN_STR :
+ case IN_STR :
{
if (echo) bb->setName("IN_STR");
// Make room for the value result
incr_stack_index(bb);
- GetElementPtrInst* gep_value =
+ GetElementPtrInst* gep_value =
cast<GetElementPtrInst>(get_stack_pointer(bb));
- CastInst* caster =
+ CastInst* caster =
new CastInst( gep_value, PointerType::get( Type::SByteTy ) );
// Make room for the count result
incr_stack_index(bb);
- GetElementPtrInst* gep_count =
+ GetElementPtrInst* gep_count =
cast<GetElementPtrInst>(get_stack_pointer(bb));
// Call scanf(3)
bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
break;
}
- case IN_NUM :
+ case IN_NUM :
{
if (echo) bb->setName("IN_NUM");
// Make room for the value result
incr_stack_index(bb);
- GetElementPtrInst* gep_value =
+ GetElementPtrInst* gep_value =
cast<GetElementPtrInst>(get_stack_pointer(bb));
// Make room for the count result
incr_stack_index(bb);
- GetElementPtrInst* gep_count =
+ GetElementPtrInst* gep_count =
cast<GetElementPtrInst>(get_stack_pointer(bb));
// Call scanf(3)
if (echo) bb->setName("IN_CHAR");
// Make room for the value result
incr_stack_index(bb);
- GetElementPtrInst* gep_value =
+ GetElementPtrInst* gep_value =
cast<GetElementPtrInst>(get_stack_pointer(bb));
// Make room for the count result
incr_stack_index(bb);
- GetElementPtrInst* gep_count =
+ GetElementPtrInst* gep_count =
cast<GetElementPtrInst>(get_stack_pointer(bb));
// Call scanf(3)
bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
break;
}
- case OUT_STR :
+ case OUT_STR :
{
if (echo) bb->setName("OUT_STR");
LoadInst* op1 = cast<LoadInst>(stack_top(bb));
std::vector<Value*> indexVec;
indexVec.push_back( Zero );
indexVec.push_back( Zero );
- GetElementPtrInst* format_gep =
+ GetElementPtrInst* format_gep =
new GetElementPtrInst( StrFormat, indexVec );
bb->getInstList().push_back( format_gep );
// Build function call arguments
bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
break;
}
- case OUT_NUM :
+ case OUT_NUM :
{
if (echo) bb->setName("OUT_NUM");
// Pop the numeric operand off the stack
std::vector<Value*> indexVec;
indexVec.push_back( Zero );
indexVec.push_back( Zero );
- GetElementPtrInst* format_gep =
+ GetElementPtrInst* format_gep =
new GetElementPtrInst( NumFormat, indexVec );
bb->getInstList().push_back( format_gep );
std::vector<Value*> indexVec;
indexVec.push_back( Zero );
indexVec.push_back( Zero );
- GetElementPtrInst* format_gep =
+ GetElementPtrInst* format_gep =
new GetElementPtrInst( ChrFormat, indexVec );
bb->getInstList().push_back( format_gep );