summaryrefslogtreecommitdiff
path: root/projects/Stacker/lib/compiler/StackerCompiler.h
blob: cd48ccb382d09ce611c4cbc12e85f86c7736b2f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
//===-- 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 <llvm/ADT/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
            unsigned optLevel, ///< Level of optimization
	    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 int64_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, int64_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
	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