[llvm-commits] CVS: llvm/projects/Stacker/lib/compiler/Lexer.l Makefile README StackerCompiler.cpp StackerCompiler.h StackerParser.y
Chris Lattner
lattner at cs.uiuc.edu
Sun Nov 23 11:54:10 PST 2003
Changes in directory llvm/projects/Stacker/lib/compiler:
Lexer.l added (r1.1)
Makefile added (r1.1)
README added (r1.1)
StackerCompiler.cpp added (r1.1)
StackerCompiler.h added (r1.1)
StackerParser.y added (r1.1)
---
Log message:
Initial stacker checkin
---
Diffs of the changes: (+2417 -0)
Index: llvm/projects/Stacker/lib/compiler/Lexer.l
diff -c /dev/null llvm/projects/Stacker/lib/compiler/Lexer.l:1.1
*** /dev/null Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/Lexer.l Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,234 ----
+ /*===-- Lexer.l - Scanner for Stacker language -----------------*- 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 flex scanner for Stacker languages files.
+ //
+ //===----------------------------------------------------------------------===*/
+
+ %option prefix="Stacker"
+ %option yylineno
+ %option nostdinit
+ %option never-interactive
+ %option batch
+ %option noyywrap
+ %option nodefault
+ %option 8bit
+ %option outfile="Lexer.cpp"
+ %option ecs
+ %option noreject
+ %option noyymore
+
+ %{
+
+ #include "StackerCompiler.h"
+ #include "StackerParser.h"
+
+ /* Conversion of text ints to binary */
+ static uint64_t IntToVal(const char *Buffer) {
+ uint64_t Result = 0;
+ for (; *Buffer; Buffer++) {
+ uint64_t OldRes = Result;
+ Result *= 10;
+ Result += *Buffer-'0';
+ if (Result < OldRes) // Uh, oh, overflow detected!!!
+ StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
+ }
+ return Result;
+ }
+
+ /* Conversion of text hexadecimal ints to binary */
+ static uint64_t HexIntToVal(const char *Buffer) {
+ uint64_t Result = 0;
+ for (; *Buffer; ++Buffer) {
+ uint64_t OldRes = Result;
+ Result *= 16;
+ char C = *Buffer;
+ if (C >= '0' && C <= '9')
+ Result += C-'0';
+ else if (C >= 'A' && C <= 'F')
+ Result += C-'A'+10;
+ else if (C >= 'a' && C <= 'f')
+ Result += C-'a'+10;
+
+ if (Result < OldRes) // Uh, oh, overflow detected!!!
+ StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
+ }
+ return Result;
+ }
+
+ #define YY_NEVER_INTERACTIVE 1
+ %}
+
+ /* Comments start with a ; and go till end of line */
+ Comment1 [#].*$
+ /* You can also embed them in ( ... ) */
+ Comment2 \(.*\)
+ /* We ignore white space */
+ White [ \t\n]
+
+ /* jdentifiers start with a % sign */
+ Identifier [A-Za-z][-A-Za-z0-9_]*
+
+ /* Strings can contain any character except " and \ */
+ String \"[^\"]*\"
+
+ /* Positive and negative integer constants*/
+ PInteger [+]?[0-9]+
+ NInteger -[0-9]+
+ HexInteger 0x[0-9A-Fa-f]+
+
+ /* Special Characters - name them to avoid flex confusion */
+ Semi [;]
+ Colon [:]
+ Less \<
+ More \>
+ LessEq \<\=
+ MoreEq \>\=
+ NotEq \<\>
+ Equal \=
+ Plus \+
+ Minus \-
+ Incr \+\+
+ Decr \-\-
+ Mult \*
+ Div \/
+ StarSlash \*\/
+ LShift \<\<
+ RShift \>\>
+ InStr \<s
+ InNum \<d
+ InChar \<c
+ OutStr \>s
+ OutNum \>d
+ OutChar \>c
+
+ %%
+
+ {Comment1} { /* Ignore comments */ }
+ {Comment2} { /* Ignore comments */ }
+
+ {Colon} { return COLON; }
+ {Semi} { return SEMI; }
+
+ TRUE { return TRUE; }
+ FALSE { return FALSE; }
+ ON { return TRUE; }
+ OFF { return FALSE; }
+ {Less} { return LESS; }
+ LT { return LESS; }
+ {More} { return MORE; }
+ GT { return MORE; }
+ {LessEq} { return LESS_EQUAL; }
+ LE { return LESS_EQUAL; }
+ {MoreEq} { return MORE_EQUAL; }
+ GE { return MORE_EQUAL; }
+ {NotEq} { return NOT_EQUAL; }
+ NE { return NOT_EQUAL; }
+ {Equal} { return EQUAL; }
+ EQ { return EQUAL; }
+
+ {Plus} { return PLUS; }
+ {Minus} { return MINUS; }
+ {Incr} { return INCR; }
+ {Decr} { return DECR; }
+ {Mult} { return MULT; }
+ {Div} { return DIV; }
+ MOD { return MODULUS; }
+ NEG { return NEGATE; }
+ ABS { return ABS; }
+ MIN { return MIN; }
+ MAX { return MAX; }
+ {StarSlash} { return STAR_SLASH; }
+
+ AND { return AND; }
+ OR { return OR; }
+ XOR { return XOR; }
+ {LShift} { return LSHIFT; }
+ {RShift} { return RSHIFT; }
+
+ DROP { return DROP; }
+ NIP { return NIP; }
+ DUP { return DUP; }
+ SWAP { return SWAP; }
+ OVER { return OVER; }
+ PICK { return PICK; }
+ SELECT { return SELECT; }
+ ROT { return ROT; }
+ RROT { return RROT; }
+ ROLL { return ROLL; }
+ TUCK { return TUCK; }
+ DROP2 { return DROP2; }
+ NIP2 { return NIP2; }
+ DUP2 { return DUP2; }
+ SWAP2 { return SWAP2; }
+ OVER2 { return OVER2; }
+ TUCK2 { return TUCK2; }
+ ROT2 { return ROT2; }
+ RROT2 { return RROT2; }
+
+ MALLOC { return MALLOC; }
+ FREE { return FREE; }
+ GET { return GET; }
+ PUT { return PUT; }
+
+ IF { return IF; }
+ ELSE { return ELSE; }
+ ENDIF { return ENDIF; }
+ WHILE { return WHILE; }
+ END { return END; }
+
+ RECURSE { return RECURSE; }
+ RETURN { return RETURN; }
+ EXIT { return EXIT; }
+ FORWARD { return FORWARD; }
+ TAB { return TAB; }
+ SPACE { return SPACE; }
+ CR { return CR; }
+
+ {InStr} { return IN_STR; }
+ {InNum} { return IN_NUM; }
+ {InChar} { return IN_CHAR; }
+
+ {OutStr} { return OUT_STR; }
+ {OutNum} { return OUT_NUM; }
+ {OutChar} { return OUT_CHAR; }
+
+ MAIN { return MAIN; }
+
+ DUMP { return DUMP; }
+
+ != { StackerCompiler::ThrowException(
+ "You probably meant to use a <> instead of !=" ); }
+
+ == { StackerCompiler::ThrowException(
+ "You probably meant to use a single = .. this isn't C"); }
+
+ {PInteger} { Stackerlval.IntegerVal = IntToVal(yytext); return INTEGER; }
+ {NInteger} { uint64_t Val = IntToVal(yytext+1);
+ // +1: we have bigger negative range
+ if (Val > (uint64_t)INT64_MAX+1)
+ StackerCompiler::ThrowException(
+ "Constant too large for signed 64 bits!");
+ Stackerlval.IntegerVal = -Val;
+ return INTEGER;
+ }
+ {HexInteger} { Stackerlval.IntegerVal = HexIntToVal(yytext+3);
+ return INTEGER;
+ }
+
+ {String} { yytext[strlen(yytext)-1] = 0; // nuke end quote
+ Stackerlval.StringVal = strdup(yytext+1); // Nuke start quote
+ return STRING;
+ }
+
+ {Identifier} { Stackerlval.StringVal = strdup(yytext); return IDENTIFIER; }
+
+ {White} { /* Ignore whitespace */ }
+ %%
Index: llvm/projects/Stacker/lib/compiler/Makefile
diff -c /dev/null llvm/projects/Stacker/lib/compiler/Makefile:1.1
*** /dev/null Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/Makefile Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,21 ----
+ ##===- projects/sample/lib/sample/Makefile -----------------*- Makefile -*-===##
+
+ #
+ # Indicate where we are relative to the top of the source tree.
+ #
+ LEVEL=../../../..
+
+ #
+ # Give the name of a library. This will build a dynamic version.
+ #
+ SHARED_LIBRARY=1
+ LIBRARYNAME=stkr_compiler
+
+ #
+ # Include Makefile.common so we know what to do.
+ #
+ include $(LEVEL)/Makefile.common
+
+ ifdef PARSE_DEBUG
+ INCLUDES += -DPARSE_DEBUG
+ endif
Index: llvm/projects/Stacker/lib/compiler/README
diff -c /dev/null llvm/projects/Stacker/lib/compiler/README:1.1
*** /dev/null Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/README Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,20 ----
+ This directory contains a sample language front end for LLVM.
+
+ It is a *very* simple/crude implementation of FORTH. It has many
+ deficiencies but provides enough basics to give you an idea of
+ what programming a new language front end for LLVM looks like.
+
+ To keep things simple, Stacker has the following limitations:
+ 1. Only a single, global stack is manipulated.
+ 2. There is no interpretation, everything is compiled.
+ 3. There's no type/bounds checking .. you're on your own.
+ 4. There's no floating point support.
+ 5. Only stdin can be read. Only stdout can be written. No other
+ file I/O is supported.
+
+ As such, this isn't a very useful language for anything other than
+ the most trivial of programs. It is, however, a good learning tool
+ (for both the author and the student).
+
+ Reid Spencer
+ 16 November 2003
Index: llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp
diff -c /dev/null llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp:1.1
*** /dev/null Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,1728 ----
+ //===-- StackerCompiler.cpp - Parser for llvm assembly files ----*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by Reid Spencer and donated to the LLVM research
+ // group and is distributed under the University of Illinois Open Source
+ // License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements the compiler for the "Stacker" language.
+ //
+ //===----------------------------------------------------------------------===//
+
+ //===----------------------------------------------------------------------===//
+ // Globasl - Global variables we use
+ //===----------------------------------------------------------------------===//
+
+ #include <llvm/Analysis/Verifier.h>
+ #include <llvm/iMemory.h>
+ #include <llvm/iOperators.h>
+ #include <llvm/iOther.h>
+ #include <llvm/iTerminators.h>
+ #include <Support/Statistic.h>
+ #include "StackerCompiler.h"
+ #include "StackerParser.h"
+ #include <string>
+
+ // Lexer/Parser defined variables and functions
+ extern std::FILE *Stackerin;
+ extern int Stackerlineno;
+ extern char* Stackertext;
+ extern int Stackerleng;
+ extern int Stackerparse();
+
+ StackerCompiler* StackerCompiler::TheInstance = 0;
+
+ static Statistic<> NumDefinitions(
+ "numdefs","The # of definitions encoutered while compiling Stacker");
+
+ StackerCompiler::StackerCompiler()
+ : CurFilename("")
+ , TheModule(0)
+ , TheFunction(0)
+ , DefinitionType(0)
+ , TheStack(0)
+ , TheIndex(0)
+ , TheScanf(0)
+ , ThePrintf(0)
+ , TheExit(0)
+ , StrFormat(0)
+ , NumFormat(0)
+ , ChrFormat(0)
+ , InStrFormat(0)
+ , InNumFormat(0)
+ , InChrFormat(0)
+ , Zero(0)
+ , One(0)
+ , Two(0)
+ , Three(0)
+ , Four(0)
+ , Five(0)
+ , IZero(0)
+ , IOne(0)
+ , ITwo(0)
+ , no_arguments()
+ , echo(false)
+ , stack_size(256)
+ , stack_type(0)
+ {
+ }
+
+ StackerCompiler::~StackerCompiler()
+ {
+ // delete TheModule; << don't do this!
+ // TheModule is passed to caller of the compile() method .. its their
+ // problem. Likewise for the other allocated objects (which become part
+ // of TheModule.
+ TheModule = 0;
+ DefinitionType = 0;
+ TheStack = 0;
+ TheIndex = 0;
+ }
+
+ Module*
+ StackerCompiler::compile(
+ const std::string& filename,
+ bool should_echo,
+ size_t the_stack_size
+ )
+ {
+ // TODO: Provide a global lock to protect the singled-threaded compiler
+ // and its global variables. Should be in guard object on the stack so
+ // that its destructor causes lock to be released (multiple exits from
+ // this function).
+
+ // Assign parameters
+ CurFilename = filename;
+ echo = should_echo;
+ stack_size = the_stack_size;
+
+ /// Default the file to read
+ FILE *F = stdin;
+
+ ///
+ if (filename != "-")
+ {
+ F = fopen(filename.c_str(), "r");
+
+ if (F == 0)
+ {
+ throw ParseException(filename,
+ "Could not open file '" + filename + "'");
+ }
+ }
+
+ Module *Result;
+ try
+ {
+ // Create the module we'll return
+ TheModule = new Module( CurFilename );
+
+ // Create a type to represent the stack. This is the same as the LLVM
+ // Assembly type [ 256 x int ]
+ stack_type = ArrayType::get( Type::IntTy, stack_size );
+
+ // Create a global variable for the stack. Note the use of appending
+ // linkage linkage so that multiple modules will make the stack larger.
+ // Also note that the last argument causes the global to be inserted
+ // automatically into the module.
+ TheStack = new GlobalVariable(
+ /*type=*/ stack_type,
+ /*isConstant=*/ false,
+ /*Linkage=*/ GlobalValue::AppendingLinkage,
+ /*initializer=*/0,
+ /*name=*/ "_stack_",
+ /*parent=*/ TheModule
+ );
+
+ // Create a global variable for indexing into the stack. Note the use
+ // of LinkOnce linkage. Only one copy of _index_ will be retained
+ // after linking
+ TheIndex = new GlobalVariable(
+ /*type=*/Type::LongTy,
+ /*isConstant=*/false,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/0,
+ /*name=*/"_index_",
+ /*parent=*/TheModule
+ );
+
+ // Create a function prototype for definitions. No parameters, no
+ // result. This is used below any time a function is created.
+ std::vector<const Type*> params; // No parameters
+ DefinitionType = FunctionType::get( Type::VoidTy, params, false );
+
+ // Create a function for printf(3)
+ params.push_back( PointerType::get( Type::SByteTy ) );
+ FunctionType* printf_type =
+ FunctionType::get( Type::IntTy, params, true );
+ ThePrintf = new Function(
+ printf_type, GlobalValue::ExternalLinkage, "printf", TheModule);
+
+ // Create a function for scanf(3)
+ TheScanf = new Function(
+ printf_type, GlobalValue::ExternalLinkage, "scanf", TheModule);
+
+ // Create a function for exit(3)
+ params.clear();
+ params.push_back( Type::IntTy );
+ FunctionType* exit_type =
+ FunctionType::get( Type::VoidTy, params, false );
+ TheExit = new Function(
+ exit_type, GlobalValue::ExternalLinkage, "exit", TheModule);
+
+ ConstantArray* str_format = ConstantArray::get("%s");
+ StrFormat = new GlobalVariable(
+ /*type=*/ArrayType::get( Type::SByteTy, 3 ),
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/str_format,
+ /*name=*/"_str_format_",
+ /*parent=*/TheModule
+ );
+
+ ConstantArray* in_str_format = ConstantArray::get(" %as");
+ InStrFormat = new GlobalVariable(
+ /*type=*/ArrayType::get( Type::SByteTy, 5 ),
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/in_str_format,
+ /*name=*/"_in_str_format_",
+ /*parent=*/TheModule
+ );
+
+ ConstantArray* num_format = ConstantArray::get("%d");
+ NumFormat = new GlobalVariable(
+ /*type=*/ArrayType::get( Type::SByteTy, 3 ),
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/num_format,
+ /*name=*/"_num_format_",
+ /*parent=*/TheModule
+ );
+
+ ConstantArray* in_num_format = ConstantArray::get(" %d");
+ InNumFormat = new GlobalVariable(
+ /*type=*/ArrayType::get( Type::SByteTy, 4 ),
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/in_num_format,
+ /*name=*/"_in_num_format_",
+ /*parent=*/TheModule
+ );
+
+ ConstantArray* chr_format = ConstantArray::get("%c");
+ ChrFormat = new GlobalVariable(
+ /*type=*/ArrayType::get( Type::SByteTy, 3 ),
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/chr_format,
+ /*name=*/"_chr_format_",
+ /*parent=*/TheModule
+ );
+
+ ConstantArray* in_chr_format = ConstantArray::get(" %c");
+ InChrFormat = new GlobalVariable(
+ /*type=*/ArrayType::get( Type::SByteTy, 4 ),
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::LinkOnceLinkage,
+ /*initializer=*/in_chr_format,
+ /*name=*/"_in_chr_format_",
+ /*parent=*/TheModule
+ );
+
+ // Get some constants so we aren't always creating them
+ Zero = ConstantInt::get( Type::LongTy, 0 );
+ One = ConstantInt::get( Type::LongTy, 1 );
+ Two = ConstantInt::get( Type::LongTy, 2 );
+ Three = ConstantInt::get( Type::LongTy, 3 );
+ Four = ConstantInt::get( Type::LongTy, 4 );
+ Five = ConstantInt::get( Type::LongTy, 5 );
+ IZero = ConstantInt::get( Type::IntTy, 0 );
+ IOne = ConstantInt::get( Type::IntTy, 1 );
+ ITwo = ConstantInt::get( Type::IntTy, 2 );
+
+ // Reset the current line number
+ Stackerlineno = 1;
+
+ // Reset the parser's input to F
+ Stackerin = F; // Set the input file.
+
+ // Let the parse know about this instance
+ TheInstance = this;
+
+ // Parse the file. The parser (see StackParser.y) will call back to
+ // the StackCompiler via the "handle*" methods
+ Stackerparse();
+
+ // Avoid potential illegal use (TheInstance might be on the stack)
+ TheInstance = 0;
+
+ } catch (...) {
+ if (F != stdin) fclose(F); // Make sure to close file descriptor
+ throw; // if an exception is thrown
+ }
+
+ // Close the file
+ if (F != stdin) fclose(F);
+
+ // Return the compiled module to the caller
+ return TheModule;
+ }
+
+ //===----------------------------------------------------------------------===//
+ // Internal Functions, used by handleXXX below.
+ // These represent the basic stack operations.
+ //===----------------------------------------------------------------------===//
+
+ Instruction*
+ StackerCompiler::incr_stack_index( BasicBlock* bb, Value* ival = 0 )
+ {
+ // Load the value from the TheIndex
+ LoadInst* loadop = new LoadInst( TheIndex );
+ bb->getInstList().push_back( loadop );
+
+ // Increment the loaded index value
+ if ( ival == 0 ) ival = One;
+ CastInst* caster = new CastInst( ival, Type::LongTy );
+ bb->getInstList().push_back( caster );
+ BinaryOperator* addop = BinaryOperator::create( Instruction::Add,
+ loadop, caster);
+ bb->getInstList().push_back( addop );
+
+ // Store the incremented value
+ StoreInst* storeop = new StoreInst( addop, TheIndex );
+ bb->getInstList().push_back( storeop );
+ return storeop;
+ }
+
+ Instruction*
+ StackerCompiler::decr_stack_index( BasicBlock* bb, Value* ival = 0 )
+ {
+ // Load the value from the TheIndex
+ LoadInst* loadop = new LoadInst( TheIndex );
+ bb->getInstList().push_back( loadop );
+
+ // Decrement the loaded index value
+ if ( ival == 0 ) ival = One;
+ CastInst* caster = new CastInst( ival, Type::LongTy );
+ bb->getInstList().push_back( caster );
+ BinaryOperator* subop = BinaryOperator::create( Instruction::Sub,
+ loadop, caster);
+ bb->getInstList().push_back( subop );
+
+ // Store the incremented value
+ StoreInst* storeop = new StoreInst( subop, TheIndex );
+ bb->getInstList().push_back( storeop );
+
+ return storeop;
+ }
+
+ Instruction*
+ StackerCompiler::get_stack_pointer( BasicBlock* bb, Value* index = 0 )
+ {
+ // Load the value of the Stack Index
+ LoadInst* loadop = new LoadInst( TheIndex );
+ bb->getInstList().push_back( loadop );
+
+ // Index into the stack to get its address. NOTE the use of two
+ // elements in this vector. The first de-references the pointer that
+ // "TheStack" represents. The second indexes into the pointed to array.
+ // Think of the first index as getting the address of the 0th element
+ // of the array.
+ std::vector<Value*> indexVec;
+ indexVec.push_back( Zero );
+
+ if ( index == 0 )
+ {
+ indexVec.push_back(loadop);
+ }
+ else
+ {
+ CastInst* caster = new CastInst( index, Type::LongTy );
+ bb->getInstList().push_back( caster );
+ BinaryOperator* subop = BinaryOperator::create(
+ Instruction::Sub, loadop, caster );
+ bb->getInstList().push_back( subop );
+ indexVec.push_back(subop);
+ }
+
+ // Get the address of the indexed stack element
+ GetElementPtrInst* gep = new GetElementPtrInst( TheStack, indexVec );
+ bb->getInstList().push_back( gep ); // Put GEP in Block
+
+ return gep;
+ }
+
+ Instruction*
+ StackerCompiler::push_value( BasicBlock* bb, Value* val )
+ {
+ // Get location of
+ incr_stack_index(bb);
+
+ // Get the stack pointer
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ get_stack_pointer( bb ) );
+
+ // Cast the value to an integer .. hopefully it works
+ CastInst* cast_inst = new CastInst( val, Type::IntTy );
+ bb->getInstList().push_back( cast_inst );
+
+ // Store the value
+ StoreInst* storeop = new StoreInst( cast_inst, gep );
+ bb->getInstList().push_back( storeop );
+
+ return storeop;
+ }
+
+ Instruction*
+ StackerCompiler::push_integer(BasicBlock* bb, int32_t value )
+ {
+ // Just push a constant integer value
+ return push_value( bb, ConstantSInt::get( Type::IntTy, value ) );
+ }
+
+ Instruction*
+ StackerCompiler::pop_integer( BasicBlock*bb )
+ {
+ // Get the stack pointer
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ get_stack_pointer( bb ));
+
+ // Load the value
+ LoadInst* load_inst = new LoadInst( gep );
+ bb->getInstList().push_back( load_inst );
+
+ // Decrement the stack index
+ decr_stack_index( bb );
+
+ // Return the value
+ return load_inst;
+ }
+
+ Instruction*
+ StackerCompiler::push_string( BasicBlock* bb, const char* value )
+ {
+ // Get length of the string
+ size_t len = strlen( value );
+
+ // Create a type for the string constant. Length is +1 for
+ // the terminating 0.
+ ArrayType* char_array = ArrayType::get( Type::SByteTy, len + 1 );
+
+ // Create an initializer for the value
+ ConstantArray* initVal = ConstantArray::get( value );
+
+ // Create an internal linkage global variable to hold the constant.
+ GlobalVariable* strconst = new GlobalVariable(
+ char_array,
+ /*isConstant=*/true,
+ GlobalValue::InternalLinkage,
+ /*initializer=*/initVal,
+ "",
+ TheModule
+ );
+
+ // Push the casted value
+ return push_value( bb, strconst );
+ }
+
+ Instruction*
+ StackerCompiler::pop_string( BasicBlock* bb )
+ {
+ // Get location of stack pointer
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ get_stack_pointer( bb ));
+
+ // Load the value from the stack
+ LoadInst* loader = new LoadInst( gep );
+ bb->getInstList().push_back( loader );
+
+ // Cast the integer to a sbyte*
+ CastInst* caster = new CastInst( loader, PointerType::get(Type::SByteTy) );
+ bb->getInstList().push_back( caster );
+
+ // Decrement stack index
+ decr_stack_index( bb );
+
+ // Return the value
+ return caster;
+ }
+
+ Instruction*
+ StackerCompiler::replace_top( BasicBlock* bb, Value* new_top, Value* index = 0 )
+ {
+ // Get the stack pointer
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ get_stack_pointer( bb, index ));
+
+ // Store the value there
+ StoreInst* store_inst = new StoreInst( new_top, gep );
+ bb->getInstList().push_back( store_inst );
+
+ // Return the value
+ return store_inst;
+ }
+
+ Instruction*
+ StackerCompiler::stack_top( BasicBlock* bb, Value* index = 0 )
+ {
+ // Get the stack pointer
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ get_stack_pointer( bb, index ));
+
+ // Load the value
+ LoadInst* load_inst = new LoadInst( gep );
+ bb->getInstList().push_back( load_inst );
+
+ // Return the value
+ return load_inst;
+ }
+
+ Instruction*
+ StackerCompiler::stack_top_string( BasicBlock* bb, Value* index = 0 )
+ {
+ // Get location of stack pointer
+ GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ get_stack_pointer( bb, index ));
+
+ // Load the value from the stack
+ LoadInst* loader = new LoadInst( gep );
+ bb->getInstList().push_back( loader );
+
+ // Cast the integer to a sbyte*
+ CastInst* caster = new CastInst( loader, PointerType::get(Type::SByteTy) );
+ bb->getInstList().push_back( caster );
+
+ // Return the value
+ return caster;
+ }
+
+ static void
+ add_block( Function*f, BasicBlock* bb )
+ {
+ if ( ! f->empty() && f->back().getTerminator() == 0 )
+ {
+ BranchInst* branch = new BranchInst(bb);
+ f->back().getInstList().push_back( branch );
+ }
+ f->getBasicBlockList().push_back( bb );
+ }
+
+
+ //===----------------------------------------------------------------------===//
+ // handleXXX - Handle semantics of parser productions
+ //===----------------------------------------------------------------------===//
+
+ Module*
+ StackerCompiler::handle_module_start( )
+ {
+ // Return the newly created module
+ return TheModule;
+ }
+
+ Module*
+ StackerCompiler::handle_module_end( Module* mod )
+ {
+ // Return the module.
+ return mod;
+ }
+
+ Module*
+ StackerCompiler::handle_definition_list_start()
+ {
+ return TheModule;
+ }
+
+ Module*
+ StackerCompiler::handle_definition_list_end( Module* mod, Function* definition )
+ {
+ if ( ! definition->empty() )
+ {
+ BasicBlock& last_block = definition->back();
+ if ( last_block.getTerminator() == 0 )
+ {
+ last_block.getInstList().push_back( new ReturnInst() );
+ }
+ }
+ // Insert the definition into the module
+ mod->getFunctionList().push_back( definition );
+
+ // Bump our (sample) statistic.
+ ++NumDefinitions;
+ return mod;
+ }
+
+ Function*
+ StackerCompiler::handle_main_definition( Function* func )
+ {
+ // Set the name of the function defined as the Stacker main
+ func->setName( "_MAIN_");
+
+ // Create the actual main for the runtime system.
+ //std::vector<const Type*> params; // No parameters
+ //FunctionType* main_type = FunctionType::get( Type::IntTy, params, false );
+ Function* SystemMain = new Function(
+ DefinitionType,
+ GlobalValue::ExternalLinkage,
+ "main", TheModule);
+
+ // Create a basic block that just calls the STACKERMAIN function. Note
+ // that the basic block is automatically inserted into the end of SystemMain
+ BasicBlock* bb = new BasicBlock( (echo?"main":"a"), SystemMain ) ;
+ bb->getInstList().push_back( new CallInst( func, no_arguments) );
+ bb->getInstList().push_back( new ReturnInst() );
+
+ // Turn "_stack_" into an initialized variable since this is the main
+ // module. This causes it to not be "external" but defined in this module.
+ TheStack->setInitializer( Constant::getNullValue(stack_type) );
+
+ // Turn "_index_" into an intialized variable for the same reason.
+ TheIndex->setInitializer( Constant::getNullValue(Type::LongTy) );
+ return func;
+ }
+
+ Function*
+ StackerCompiler::handle_forward( char * name )
+ {
+ // Just create a placeholder function
+ Function* the_function = new Function (
+ DefinitionType,
+ GlobalValue::ExternalLinkage,
+ name );
+ assert( the_function->isExternal() );
+
+ free( name );
+ return the_function;
+ }
+
+ Function*
+ StackerCompiler::handle_definition( char * name, Function* f )
+ {
+ // Look up the function name in the module to see if it was forward
+ // declared.
+ Function* existing_function = TheModule->getNamedFunction( name );
+
+ #if 0
+ // If the function already exists...
+ if ( existing_function )
+ {
+ // Just get rid of the placeholder
+ existing_function->dropAllReferences();
+ delete existing_function;
+ }
+ #endif
+
+ // Just set the name of the function now that we know what it is.
+ f->setName( name );
+
+ free( name );
+
+ return f;
+ }
+
+ Function*
+ StackerCompiler::handle_word_list_start()
+ {
+ TheFunction = new Function(DefinitionType, GlobalValue::ExternalLinkage);
+ return TheFunction;
+ }
+
+ Function*
+ StackerCompiler::handle_word_list_end( Function* f, BasicBlock* bb )
+ {
+ add_block( f, bb );
+ return f;
+ }
+
+ BasicBlock*
+ StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
+ {
+ // Create a basic block for the preamble
+ BasicBlock* bb = new BasicBlock((echo?"if":""));
+
+ // Get the condition value
+ LoadInst* cond = cast<LoadInst>( pop_integer(bb) );
+
+ // Compare the condition against 0
+ SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond,
+ ConstantSInt::get( Type::IntTy, 0) );
+ bb->getInstList().push_back( cond_inst );
+
+ // Create an exit block
+ BasicBlock* exit_bb = new BasicBlock((echo?"endif":""));
+
+ // Create the true_block
+ BasicBlock* true_bb = new BasicBlock((echo?"then":""));
+
+ // Create the false_block
+ BasicBlock* false_bb = 0;
+ if ( ifFalse ) false_bb = new BasicBlock((echo?"else":""));
+
+ // Create a branch on the SetCond
+ BranchInst* br_inst = new BranchInst( true_bb,
+ ( ifFalse ? false_bb : exit_bb ), cond_inst );
+ bb->getInstList().push_back( br_inst );
+
+ // Fill the true block
+ std::vector<Value*> args;
+ if ( Function* true_func = TheModule->getNamedFunction(ifTrue) )
+ {
+ true_bb->getInstList().push_back(
+ new CallInst( true_func, args ) );
+ true_bb->getInstList().push_back(
+ new BranchInst( exit_bb ) );
+ }
+ else
+ {
+ ThrowException(std::string("Function '") + ifTrue +
+ "' must be declared first.'");
+ }
+
+ free( ifTrue );
+
+ // Fill the false block
+ if ( false_bb )
+ {
+ if ( Function* false_func = TheModule->getNamedFunction(ifFalse) )
+ {
+ false_bb->getInstList().push_back(
+ new CallInst( false_func, args ) );
+ false_bb->getInstList().push_back(
+ new BranchInst( exit_bb ) );
+ }
+ else
+ {
+ ThrowException(std::string("Function '") + ifFalse +
+ "' must be declared first.'");
+ }
+ free( ifFalse );
+ }
+
+ // Add the blocks to the function
+ add_block( TheFunction, bb );
+ add_block( TheFunction, true_bb );
+ if ( false_bb ) add_block( TheFunction, false_bb );
+
+ return exit_bb;
+ }
+
+ BasicBlock*
+ StackerCompiler::handle_while( char* todo )
+ {
+
+ // Create a basic block for the loop test
+ BasicBlock* test = new BasicBlock((echo?"while":""));
+
+ // Create an exit block
+ BasicBlock* exit = new BasicBlock((echo?"end":""));
+
+ // Create a loop body block
+ BasicBlock* body = new BasicBlock((echo?"do":""));
+
+ // Create a root node
+ BasicBlock* bb = new BasicBlock((echo?"root":""));
+ BranchInst* root_br_inst = new BranchInst( test );
+ bb->getInstList().push_back( root_br_inst );
+
+ // Pop the condition value
+ LoadInst* cond = cast<LoadInst>( stack_top(test) );
+
+ // Compare the condition against 0
+ SetCondInst* cond_inst = new SetCondInst(
+ Instruction::SetNE, cond, ConstantSInt::get( Type::IntTy, 0) );
+ test->getInstList().push_back( cond_inst );
+
+ // Add the branch instruction
+ BranchInst* br_inst = new BranchInst( body, exit, cond_inst );
+ test->getInstList().push_back( br_inst );
+
+ // Fill in the body
+ std::vector<Value*> args;
+ if ( Function* body_func = TheModule->getNamedFunction(todo) )
+ {
+ body->getInstList().push_back( new CallInst( body_func, args ) );
+ body->getInstList().push_back( new BranchInst( test ) );
+ }
+ else
+ {
+ ThrowException(std::string("Function '") + todo +
+ "' must be declared first.'");
+ }
+
+ free( todo );
+
+ // Add the blocks
+ add_block( TheFunction, bb );
+ add_block( TheFunction, test );
+ add_block( TheFunction, body );
+
+ return exit;
+ }
+
+ BasicBlock*
+ StackerCompiler::handle_identifier( char * name )
+ {
+ Function* func = TheModule->getNamedFunction( name );
+ BasicBlock* bb = new BasicBlock((echo?"call":""));
+ if ( func )
+ {
+ CallInst* call_def = new CallInst( func , no_arguments );
+ bb->getInstList().push_back( call_def );
+ }
+ else
+ {
+ ThrowException(std::string("Definition '") + name +
+ "' must be defined before it can be used.");
+ }
+
+ free( name );
+ return bb;
+ }
+
+ BasicBlock*
+ StackerCompiler::handle_string( char * value )
+ {
+ // Create a new basic block for the push operation
+ BasicBlock* bb = new BasicBlock((echo?"string":""));
+
+ // Push the string onto the stack
+ push_string(bb, value);
+
+ // Free the strdup'd string
+ free( value );
+
+ return bb;
+ }
+
+ BasicBlock*
+ StackerCompiler::handle_integer( const int32_t value )
+ {
+ // Create a new basic block for the push operation
+ BasicBlock* bb = new BasicBlock((echo?"int":""));
+
+ // Push the integer onto the stack
+ push_integer(bb, value );
+
+ return bb;
+ }
+
+ BasicBlock*
+ StackerCompiler::handle_word( int tkn )
+ {
+ // Create a new basic block to hold the instruction(s)
+ BasicBlock* bb = new BasicBlock();
+
+ /* Fill the basic block with the appropriate instructions */
+ switch ( tkn )
+ {
+ case DUMP : // Dump the stack (debugging aid)
+ {
+ if (echo) bb->setName("DUMP");
+ Function* f = TheModule->getOrInsertFunction(
+ "_stacker_dump_stack_", DefinitionType);
+ std::vector<Value*> args;
+ bb->getInstList().push_back( new CallInst( f, args ) );
+ break;
+ }
+
+ // Logical Operations
+ case TRUE : // -- -1
+ {
+ if (echo) bb->setName("TRUE");
+ push_integer(bb,-1);
+ break;
+ }
+ case FALSE : // -- 0
+ {
+ if (echo) bb->setName("FALSE");
+ push_integer(bb,0);
+ break;
+ }
+ case LESS : // w1 w2 -- w2<w1
+ {
+ if (echo) bb->setName("LESS");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetLT, op1, op2 );
+ bb->getInstList().push_back( cond_inst );
+ push_value( bb, cond_inst );
+ break;
+ }
+ case MORE : // w1 w2 -- w2>w1
+ {
+ if (echo) bb->setName("MORE");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetGT, op1, op2 );
+ bb->getInstList().push_back( cond_inst );
+ push_value( bb, cond_inst );
+ break;
+ }
+ case LESS_EQUAL : // w1 w2 -- w2<=w1
+ {
+ if (echo) bb->setName("LE");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetLE, op1, op2 );
+ bb->getInstList().push_back( cond_inst );
+ push_value( bb, cond_inst );
+ break;
+ }
+ case MORE_EQUAL : // w1 w2 -- w2>=w1
+ {
+ if (echo) bb->setName("GE");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetGE, op1, op2 );
+ bb->getInstList().push_back( cond_inst );
+ push_value( bb, cond_inst );
+ break;
+ }
+ case NOT_EQUAL : // w1 w2 -- w2!=w1
+ {
+ if (echo) bb->setName("NE");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetNE, op1, op2 );
+ bb->getInstList().push_back( cond_inst );
+ push_value( bb, cond_inst );
+ break;
+ }
+ case EQUAL : // w1 w2 -- w1==w2
+ {
+ if (echo) bb->setName("EQ");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetEQ, op1, op2 );
+ bb->getInstList().push_back( cond_inst );
+ push_value( bb, cond_inst );
+ break;
+ }
+
+ // Arithmetic Operations
+ case PLUS : // w1 w2 -- w2+w1
+ {
+ if (echo) bb->setName("ADD");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* addop =
+ BinaryOperator::create( Instruction::Add, op1, op2);
+ bb->getInstList().push_back( addop );
+ push_value( bb, addop );
+ break;
+ }
+ case MINUS : // w1 w2 -- w2-w1
+ {
+ if (echo) bb->setName("SUB");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* subop =
+ BinaryOperator::create( Instruction::Sub, op1, op2);
+ bb->getInstList().push_back( subop );
+ push_value( bb, subop );
+ break;
+ }
+ case INCR : // w1 -- w1+1
+ {
+ if (echo) bb->setName("INCR");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* addop =
+ BinaryOperator::create( Instruction::Add, op1, IOne );
+ bb->getInstList().push_back( addop );
+ push_value( bb, addop );
+ break;
+ }
+ case DECR : // w1 -- w1-1
+ {
+ if (echo) bb->setName("DECR");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* subop = BinaryOperator::create( Instruction::Sub, op1,
+ ConstantSInt::get( Type::IntTy, 1 ) );
+ bb->getInstList().push_back( subop );
+ push_value( bb, subop );
+ break;
+ }
+ case MULT : // w1 w2 -- w2*w1
+ {
+ if (echo) bb->setName("MUL");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* multop =
+ BinaryOperator::create( Instruction::Mul, op1, op2);
+ bb->getInstList().push_back( multop );
+ push_value( bb, multop );
+ break;
+ }
+ case DIV :// w1 w2 -- w2/w1
+ {
+ if (echo) bb->setName("DIV");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* divop =
+ BinaryOperator::create( Instruction::Div, op1, op2);
+ bb->getInstList().push_back( divop );
+ push_value( bb, divop );
+ break;
+ }
+ case MODULUS : // w1 w2 -- w2%w1
+ {
+ if (echo) bb->setName("MOD");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ BinaryOperator* divop =
+ BinaryOperator::create( Instruction::Rem, op1, op2);
+ bb->getInstList().push_back( divop );
+ push_value( bb, divop );
+ break;
+ }
+ case STAR_SLASH : // w1 w2 w3 -- (w3*w2)/w1
+ {
+ if (echo) bb->setName("STAR_SLASH");
+ // Get the operands
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op3 = cast<LoadInst>(pop_integer(bb));
+
+ // Multiply the first two
+ BinaryOperator* multop =
+ BinaryOperator::create( Instruction::Mul, op1, op2);
+ bb->getInstList().push_back( multop );
+
+ // Divide by the third operand
+ BinaryOperator* divop =
+ BinaryOperator::create( Instruction::Div, multop, op3);
+ bb->getInstList().push_back( divop );
+
+ // Push the result
+ push_value( bb, divop );
+
+ break;
+ }
+ case NEGATE : // w1 -- -w1
+ {
+ if (echo) bb->setName("NEG");
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ // APPARENTLY, the following doesn't work:
+ // BinaryOperator* negop = BinaryOperator::createNeg( op1 );
+ // bb->getInstList().push_back( negop );
+ // So we'll multiply by -1 (ugh)
+ BinaryOperator* multop = BinaryOperator::create( Instruction::Mul, op1,
+ ConstantSInt::get( Type::IntTy, -1 ) );
+ bb->getInstList().push_back( multop );
+ push_value( bb, multop );
+ break;
+ }
+ case ABS : // w1 -- |w1|
+ {
+ if (echo) bb->setName("ABS");
+ // Get the top of stack value
+ LoadInst* op1 = cast<LoadInst>(stack_top(bb));
+
+ // Determine if its negative
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetLT, op1, IZero );
+ bb->getInstList().push_back( cond_inst );
+
+ // Create a block for storing the result
+ BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
+
+ // Create a block for making it a positive value
+ BasicBlock* pos_bb = new BasicBlock((echo?"neg":""));
+
+ // Create the branch on the SetCond
+ BranchInst* br_inst = new BranchInst( pos_bb, exit_bb, cond_inst );
+ bb->getInstList().push_back( br_inst );
+
+ // Fill out the negation block
+ LoadInst* pop_op = cast<LoadInst>( pop_integer(pos_bb) );
+ BinaryOperator* neg_op = BinaryOperator::createNeg( pop_op );
+ pos_bb->getInstList().push_back( neg_op );
+ push_value( pos_bb, neg_op );
+ pos_bb->getInstList().push_back( new BranchInst( exit_bb ) );
+
+ // Add the new blocks in the correct order
+ add_block( TheFunction, bb );
+ add_block( TheFunction, pos_bb );
+ bb = exit_bb;
+ break;
+ }
+ case MIN : // w1 w2 -- (w2<w1?w2:w1)
+ {
+ if (echo) bb->setName("MIN");
+
+ // Create the three blocks
+ BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
+ BasicBlock* op1_block = new BasicBlock((echo?"less":""));
+ BasicBlock* op2_block = new BasicBlock((echo?"more":""));
+
+ // Get the two operands
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+
+ // Compare them
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetLT, op1, op2);
+ bb->getInstList().push_back( cond_inst );
+
+ // Create a branch on the SetCond
+ BranchInst* br_inst =
+ new BranchInst( op1_block, op2_block, cond_inst );
+ bb->getInstList().push_back( br_inst );
+
+ // Create a block for pushing the first one
+ push_value(op1_block, op1);
+ op1_block->getInstList().push_back( new BranchInst( exit_bb ) );
+
+ // Create a block for pushing the second one
+ push_value(op2_block, op2);
+ op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
+
+ // Add the blocks
+ add_block( TheFunction, bb );
+ add_block( TheFunction, op1_block );
+ add_block( TheFunction, op2_block );
+ bb = exit_bb;
+ break;
+ }
+ case MAX : // w1 w2 -- (w2>w1?w2:w1)
+ {
+ if (echo) bb->setName("MAX");
+ // Get the two operands
+ LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+
+ // Compare them
+ SetCondInst* cond_inst =
+ new SetCondInst( Instruction::SetGT, op1, op2);
+ bb->getInstList().push_back( cond_inst );
+
+ // Create an exit block
+ BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
+
+ // Create a block for pushing the larger one
+ BasicBlock* op1_block = new BasicBlock((echo?"more":""));
+ push_value(op1_block, op1);
+ 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::Shr, 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, IOne );
+ 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, IOne );
+ bb->getInstList().push_back( index );
+ LoadInst* Xm = cast<LoadInst>( stack_top(bb, index ) );
+ BinaryOperator* n_plus_1 =
+ BinaryOperator::create( Instruction::Add, n, IOne );
+ 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));
+
+ // Call exit(3)
+ std::vector<Value*> params;
+ params.push_back(op1);
+ 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 newline)
+ ConstantSInt* newline = ConstantSInt::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 newline)
+ ConstantSInt* newline = ConstantSInt::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)
+ ConstantSInt* newline = ConstantSInt::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;
+ }
Index: llvm/projects/Stacker/lib/compiler/StackerCompiler.h
diff -c /dev/null llvm/projects/Stacker/lib/compiler/StackerCompiler.h:1.1
*** /dev/null Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/StackerCompiler.h Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,224 ----
+ //===-- StackerCompiler.h - Interface to the Stacker Compiler ---*- 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 header file defines the various variables that are shared among the
+ // different components of the parser...
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef LLVM_STACKERCOMPILER_H
+ #define LLVM_STACKERCOMPILER_H
+
+ #include <llvm/Constants.h>
+ #include <llvm/DerivedTypes.h>
+ #include <llvm/Function.h>
+ #include <llvm/Instruction.h>
+ #include <llvm/Module.h>
+ #include <llvm/Assembly/Parser.h>
+ #include <Support/StringExtras.h>
+
+ using namespace llvm;
+
+ // Global variables exported from the lexer...
+ extern std::FILE *Stackerin;
+ extern int Stackerlineno;
+ extern char* Stackertext;
+ extern int Stackerleng;
+
+ /// @brief This class provides the Compiler for the Stacker language.
+ ///
+ /// The main method to call is \c compile. The other methods are
+ /// all internal to the compiler and protected. In general the
+ /// handle_* methods are called by the BISON generated parser
+ /// (see StackerParser.y). The methods returning Instruction* all
+ /// produce some snippet of code to manipulate the stack in some
+ /// way. These functions are just conveniences as they are used
+ /// often by the compiler.
+ class StackerCompiler
+ {
+ /// @name Constructors and Operators
+ /// @{
+ public:
+ /// Default Constructor
+ StackerCompiler();
+
+ /// Destructor
+ ~StackerCompiler();
+ private:
+ /// Do not copy StackerCompilers
+ StackerCompiler(const StackerCompiler&);
+
+ /// Do not copy StackerCompilers.
+ StackerCompiler& operator=(const StackerCompiler& );
+
+ /// @}
+ /// @name High Level Interface
+ /// @{
+ public:
+ /// @brief Compile a single file to LLVM bytecode.
+ ///
+ /// To use the StackerCompiler, just create one on
+ /// the stack and call this method.
+ Module* compile(
+ const std::string& filename, ///< File to compile
+ bool echo, ///< Causes compiler to echo output
+ size_t stack_size ); ///< Size of generated stack
+ /// @}
+ /// @name Accessors
+ /// @{
+ public:
+ /// @brief Returns the name of the file being compiled.
+ std::string& filename() { return CurFilename; }
+
+ /// @}
+ /// @name Parse Handling Methods
+ /// @{
+ private:
+ /// Allow only the parser to access these methods. No
+ /// one else should call them.
+ friend int Stackerparse();
+
+ /// @brief Handle the start of a module
+ Module* handle_module_start();
+
+ /// @brief Handle the end of a module
+ /// @param mod The module we're defining.
+ Module* handle_module_end( Module* mod );
+
+ /// @brief Handle the start of a list of definitions
+ Module* handle_definition_list_start( );
+
+ /// @brief Handle the end of a list of definitions
+ /// @param mod The module we're constructing
+ /// @param definition A definition (function) to add to the module
+ Module* handle_definition_list_end( Module* mod, Function* definition );
+
+ /// @brief Handle creation of the MAIN definition
+ /// @param func The function to be used as the MAIN definition
+ Function* handle_main_definition( Function* func );
+
+ /// @brief Handle a forward definition
+ /// @param name The name of the definition being declared
+ Function* handle_forward( char* name );
+
+ /// @brief Handle a general definition
+ /// @param name The name of the definition being defined
+ /// @param func The Function definition.
+ Function* handle_definition( char* name, Function* func );
+
+ /// @brief Handle the start of a definition's word list
+ Function* handle_word_list_start();
+
+ /// @brief Handle the end of a definition's word list
+ /// @param func The function to which the basic block is added
+ /// @param next The block to add to the function
+ Function* handle_word_list_end( Function* func, BasicBlock* next );
+
+ /// @brief Handle an if statement, possibly without an else
+ /// @brief ifTrue The block to execute if true
+ /// @brief ifFalse The optional block to execute if false
+ BasicBlock* handle_if( char* ifTrue, char* ifFalse = 0 );
+
+ /// @brief Handle a while statement
+ /// @brief todo The block to repeatedly execute
+ BasicBlock* handle_while( char* todo );
+
+ /// @brief Handle an identifier to call the identified definition
+ /// @param name The name of the identifier to be called.
+ BasicBlock* handle_identifier( char * name );
+
+ /// @brief Handle the push of a string onto the stack
+ /// @param value The string to be pushed.
+ BasicBlock* handle_string( char * value );
+
+ /// @brief Handle the push of an integer onto the stack.
+ /// @param value The integer value to be pushed.
+ BasicBlock* handle_integer( const int32_t value );
+
+ /// @brief Handle one of the reserved words (given as a token)
+ BasicBlock* handle_word( int tkn );
+
+ /// @}
+ /// @name Utility functions
+ /// @{
+ public:
+ /// @brief Throws an exception to indicate an error
+ /// @param message The message to be output
+ /// @param line Override for the current line no
+ static inline void ThrowException( const std::string &message,
+ int line = -1)
+ {
+ if (line == -1) line = Stackerlineno;
+ // TODO: column number in exception
+ throw ParseException(TheInstance->CurFilename, message, line);
+ }
+ private:
+ /// @brief Generate code to increment the stack index
+ Instruction* incr_stack_index( BasicBlock* bb, Value* );
+ /// @brief Generate code to decrement the stack index.
+ Instruction* decr_stack_index( BasicBlock* bb, Value* );
+ /// @brief Generate code to dereference the top of stack.
+ Instruction* get_stack_pointer( BasicBlock* bb, Value* );
+ /// @brief Generate code to push any value onto the stack.
+ Instruction* push_value( BasicBlock* bb, Value* value );
+ /// @brief Generate code to push a constant integer onto the stack.
+ Instruction* push_integer( BasicBlock* bb, int32_t value );
+ /// @brief Generate code to pop an integer off the stack.
+ Instruction* pop_integer( BasicBlock* bb );
+ /// @brief Generate code to push a string pointer onto the stack.
+ Instruction* push_string( BasicBlock* bb, const char* value );
+ /// @brief Generate code to pop a string pointer off the stack.
+ Instruction* pop_string( BasicBlock* bb );
+ /// @brief Generate code to get the top stack element.
+ Instruction* stack_top( BasicBlock* bb, Value* index );
+ /// @brief Generate code to get the top stack element as a string.
+ Instruction* stack_top_string( BasicBlock* bb, Value* index );
+ /// @brief Generate code to replace the top element of the stack.
+ Instruction* replace_top( BasicBlock* bb, Value* new_top, Value* index);
+
+ /// @}
+ /// @name Data Members (used during parsing)
+ /// @{
+ public:
+ static StackerCompiler* TheInstance; ///< The instance for the parser
+
+ private:
+ std::string CurFilename; ///< Current file name
+ Module* TheModule; ///< Module instance we'll build
+ Function* TheFunction; ///< Function we're building
+ FunctionType* DefinitionType; ///< FT for Definitions
+ GlobalVariable* TheStack; ///< For referencing _stack_
+ GlobalVariable* TheIndex; ///< For referencing _index_
+ Function* TheScanf; ///< External input function
+ Function* ThePrintf; ///< External output function
+ Function* TheExit; ///< External exit function
+ GlobalVariable* StrFormat; ///< Format for strings
+ GlobalVariable* NumFormat; ///< Format for numbers
+ GlobalVariable* ChrFormat; ///< Format for chars
+ GlobalVariable* InStrFormat; ///< Format for input strings
+ GlobalVariable* InNumFormat; ///< Format for input numbers
+ GlobalVariable* InChrFormat; ///< Format for input chars
+ ConstantInt* Zero; ///< long constant 0
+ ConstantInt* One; ///< long constant 1
+ ConstantInt* Two; ///< long constant 2
+ ConstantInt* Three; ///< long constant 3
+ ConstantInt* Four; ///< long constant 4
+ ConstantInt* Five; ///< long constant 5
+ ConstantInt* IZero; ///< int constant 0
+ ConstantInt* IOne; ///< int constant 1
+ ConstantInt* ITwo; ///< int constant 2
+ std::vector<Value*> no_arguments; ///< no arguments for Stacker
+ bool echo; ///< Echo flag
+ size_t stack_size; ///< Size of stack to gen.
+ ArrayType* stack_type; ///< The type of the stack
+ /// @}
+ };
+
+ #endif
Index: llvm/projects/Stacker/lib/compiler/StackerParser.y
diff -c /dev/null llvm/projects/Stacker/lib/compiler/StackerParser.y:1.1
*** /dev/null Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/StackerParser.y Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,190 ----
+ //===-- llvmAsmParser.y - Parser for llvm assembly files --------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements the bison parser for LLVM assembly languages files.
+ //
+ //===----------------------------------------------------------------------===//
+
+ %debug
+
+ %{
+ #include "StackerCompiler.h"
+ #include "llvm/SymbolTable.h"
+ #include "llvm/Module.h"
+ #include "llvm/iTerminators.h"
+ #include "llvm/iMemory.h"
+ #include "llvm/iOperators.h"
+ #include "llvm/iPHINode.h"
+ #include "Support/STLExtras.h"
+ #include "Support/DepthFirstIterator.h"
+ #include <list>
+ #include <utility>
+ #include <algorithm>
+
+ #define YYERROR_VERBOSE 1
+ #define SCI StackerCompiler::TheInstance
+
+ int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
+ int yylex(); // declaration" of xxx warnings.
+ int yyparse();
+
+ %}
+
+ %union
+ {
+ llvm::Module* ModuleVal;
+ llvm::Function* FunctionVal;
+ llvm::BasicBlock* BasicBlockVal;
+ uint32_t IntegerVal;
+ char* StringVal;
+ }
+
+ /* Typed Productions */
+ %type <ModuleVal> Module DefinitionList
+ %type <FunctionVal> Definition ForwardDef ColonDef MainDef
+ %type <FunctionVal> WordList
+ %type <BasicBlockVal> Word
+
+ /* Typed Tokens */
+ %token <IntegerVal> INTEGER
+ %token <StringVal> STRING IDENTIFIER
+
+ /* Terminal Tokens */
+ %token SEMI COLON FORWARD MAIN DUMP
+ %token TRUE FALSE LESS MORE LESS_EQUAL MORE_EQUAL NOT_EQUAL EQUAL
+ %token PLUS MINUS INCR DECR MULT DIV MODULUS NEGATE ABS MIN MAX STAR_SLASH
+ %token AND OR XOR LSHIFT RSHIFT
+ %token DROP DROP2 NIP NIP2 DUP DUP2 SWAP SWAP2 OVER OVER2 ROT ROT2
+ %token RROT RROT2 TUCK TUCK2 ROLL PICK SELECT
+ %token MALLOC FREE GET PUT
+ %token IF ELSE ENDIF WHILE END RECURSE RETURN EXIT
+ %token TAB SPACE CR IN_STR IN_NUM IN_CHAR OUT_STR OUT_NUM OUT_CHAR
+
+ /* Start Token */
+ %start Module
+
+ %%
+
+ /* A module is just a DefinitionList */
+ Module : { SCI->handle_module_start( ); }
+ DefinitionList { $$ = SCI->handle_module_end( $2 ); } ;
+
+ /* A Definitionlist is just a sequence of definitions */
+ DefinitionList : DefinitionList Definition { $$ = SCI->handle_definition_list_end( $1, $2 ); }
+ | /* empty */ { $$ = SCI->handle_definition_list_start(); } ;
+
+ /* A definition can be one of three flavors */
+ Definition : ForwardDef { $$ = $1; }
+ | ColonDef { $$ = $1; }
+ | MainDef { $$ = $1; } ;
+
+ /* Forward definitions just introduce a name */
+ ForwardDef : FORWARD IDENTIFIER SEMI { $$ = SCI->handle_forward( $2 ); } ;
+
+ /* The main definition has to generate additional code so we treat it specially */
+ MainDef : COLON MAIN WordList SEMI { $$ = SCI->handle_main_definition($3); } ;
+
+ /* Regular definitions have a name and a WordList */
+ ColonDef : COLON IDENTIFIER WordList SEMI { $$ = SCI->handle_definition( $2, $3 ); } ;
+
+ /* A WordList is just a sequence of words */
+ WordList : WordList Word { $$ = SCI->handle_word_list_end( $1, $2 ); }
+ | /* empty */ { $$ = SCI->handle_word_list_start() } ;
+
+ /* A few "words" have a funky syntax */
+ /* FIXME: The body of compound words can currently only be function calls */
+ /* This is not acceptable, it should be a WordList, but that produces a Function */
+ /* Which is hard to merge into the function the compound statement is working on */
+ Word : IF IDENTIFIER ELSE IDENTIFIER ENDIF { $$ = SCI->handle_if( $2, $4 ); }
+ | IF IDENTIFIER ENDIF { $$ = SCI->handle_if( $2 ); }
+ | WHILE IDENTIFIER END { $$ = SCI->handle_while( $2 ); } ;
+
+ /* A few words are handled specially */
+ Word : IDENTIFIER { $$ = SCI->handle_identifier( $1 ); } ;
+ Word : STRING { $$ = SCI->handle_string( $1 ); } ;
+ Word : INTEGER { $$ = SCI->handle_integer( $1 ); } ;
+
+ /* Everything else is a terminal symbol and goes to handle_word */
+ Word : TRUE { $$ = SCI->handle_word( TRUE ); } ;
+ Word : FALSE { $$ = SCI->handle_word( FALSE ); } ;
+ Word : LESS { $$ = SCI->handle_word( LESS ); } ;
+ Word : MORE { $$ = SCI->handle_word( MORE ); } ;
+ Word : LESS_EQUAL { $$ = SCI->handle_word( LESS_EQUAL ); } ;
+ Word : MORE_EQUAL { $$ = SCI->handle_word( MORE_EQUAL ); } ;
+ Word : NOT_EQUAL { $$ = SCI->handle_word( NOT_EQUAL ); } ;
+ Word : EQUAL { $$ = SCI->handle_word( EQUAL ); } ;
+ Word : PLUS { $$ = SCI->handle_word( PLUS ); } ;
+ Word : MINUS { $$ = SCI->handle_word( MINUS ); } ;
+ Word : INCR { $$ = SCI->handle_word( INCR ); } ;
+ Word : DECR { $$ = SCI->handle_word( DECR ); } ;
+ Word : MULT { $$ = SCI->handle_word( MULT ); } ;
+ Word : DIV { $$ = SCI->handle_word( DIV ); } ;
+ Word : MODULUS { $$ = SCI->handle_word( MODULUS ); } ;
+ Word : NEGATE { $$ = SCI->handle_word( NEGATE ); } ;
+ Word : ABS { $$ = SCI->handle_word( ABS ); } ;
+ Word : MIN { $$ = SCI->handle_word( MIN ); } ;
+ Word : MAX { $$ = SCI->handle_word( MAX ); } ;
+ Word : STAR_SLASH { $$ = SCI->handle_word( STAR_SLASH ); } ;
+ Word : AND { $$ = SCI->handle_word( AND ); } ;
+ Word : OR { $$ = SCI->handle_word( OR ); } ;
+ Word : XOR { $$ = SCI->handle_word( XOR ); } ;
+ Word : LSHIFT { $$ = SCI->handle_word( LSHIFT ); } ;
+ Word : RSHIFT { $$ = SCI->handle_word( RSHIFT ); } ;
+ Word : DROP { $$ = SCI->handle_word( DROP ); } ;
+ Word : DROP2 { $$ = SCI->handle_word( DROP2 ); } ;
+ Word : NIP { $$ = SCI->handle_word( NIP ); } ;
+ Word : NIP2 { $$ = SCI->handle_word( NIP2 ); } ;
+ Word : DUP { $$ = SCI->handle_word( DUP ); } ;
+ Word : DUP2 { $$ = SCI->handle_word( DUP2 ); } ;
+ Word : SWAP { $$ = SCI->handle_word( SWAP ); } ;
+ Word : SWAP2 { $$ = SCI->handle_word( SWAP2 ); } ;
+ Word : OVER { $$ = SCI->handle_word( OVER ); } ;
+ Word : OVER2 { $$ = SCI->handle_word( OVER2 ); } ;
+ Word : ROT { $$ = SCI->handle_word( ROT ); } ;
+ Word : ROT2 { $$ = SCI->handle_word( ROT2 ); } ;
+ Word : RROT { $$ = SCI->handle_word( RROT ); } ;
+ Word : RROT2 { $$ = SCI->handle_word( RROT2 ); } ;
+ Word : TUCK { $$ = SCI->handle_word( TUCK ); } ;
+ Word : TUCK2 { $$ = SCI->handle_word( TUCK2 ); } ;
+ Word : ROLL { $$ = SCI->handle_word( ROLL ); } ;
+ Word : PICK { $$ = SCI->handle_word( PICK ); } ;
+ Word : SELECT { $$ = SCI->handle_word( SELECT ); } ;
+ Word : MALLOC { $$ = SCI->handle_word( MALLOC ); } ;
+ Word : FREE { $$ = SCI->handle_word( FREE ); } ;
+ Word : GET { $$ = SCI->handle_word( GET ); } ;
+ Word : PUT { $$ = SCI->handle_word( PUT ); } ;
+ Word : RECURSE { $$ = SCI->handle_word( RECURSE ); } ;
+ Word : RETURN { $$ = SCI->handle_word( RETURN ); } ;
+ Word : EXIT { $$ = SCI->handle_word( EXIT ); } ;
+ Word : TAB { $$ = SCI->handle_word( TAB ); };
+ Word : SPACE { $$ = SCI->handle_word( SPACE ); } ;
+ Word : CR { $$ = SCI->handle_word( CR ); } ;
+ Word : IN_STR { $$ = SCI->handle_word( IN_STR ); } ;
+ Word : IN_NUM { $$ = SCI->handle_word( IN_NUM ); } ;
+ Word : IN_CHAR { $$ = SCI->handle_word( IN_CHAR ); } ;
+ Word : OUT_STR { $$ = SCI->handle_word( OUT_STR ); } ;
+ Word : OUT_NUM { $$ = SCI->handle_word( OUT_NUM ); } ;
+ Word : OUT_CHAR { $$ = SCI->handle_word( OUT_CHAR ); } ;
+ Word : DUMP { $$ = SCI->handle_word( DUMP ); } ;
+
+ %%
+
+ /* Handle messages a little more nicely than the default yyerror */
+ int yyerror(const char *ErrorMsg) {
+ std::string where
+ = std::string((SCI->filename() == "-") ? std::string("<stdin>") : SCI->filename())
+ + ":" + utostr((unsigned) Stackerlineno ) + ": ";
+ std::string errMsg = std::string(ErrorMsg) + "\n" + where + " while reading ";
+ if (yychar == YYEMPTY)
+ errMsg += "end-of-file.";
+ else
+ errMsg += "token: '" + std::string(Stackertext, Stackerleng) + "'";
+ StackerCompiler::ThrowException(errMsg);
+ return 0;
+ }
More information about the llvm-commits
mailing list