Completed editing of PythonLangImpl4.rst
This commit is contained in:
parent
1b67d32f4b
commit
f74f5129bd
1 changed files with 437 additions and 356 deletions
|
|
@ -188,8 +188,6 @@ by running it after our newly created function is constructed (in
|
||||||
return_value = self.body.CodeGen()
|
return_value = self.body.CodeGen()
|
||||||
g_llvm_builder.ret(return_value)
|
g_llvm_builder.ret(return_value)
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
# Validate the generated code, checking for consistency.
|
# Validate the generated code, checking for consistency.
|
||||||
function.verify()
|
function.verify()
|
||||||
|
|
||||||
|
|
@ -403,22 +401,28 @@ example, we can create a C file with the following simple function:
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
double putchard(double x) {
|
double putchard(double x) {
|
||||||
putchar((char)x); return 0; }
|
putchar((char)x); return 0;
|
||||||
|
}
|
||||||
|
|
||||||
We can then compile this into a shared library with GCC:
|
We can then compile this into a shared library with GCC::
|
||||||
|
|
||||||
gcc -shared -fPIC -o putchard.so putchard.c
|
gcc -shared -fPIC -o putchard.so putchard.c
|
||||||
|
|
||||||
Now we can load this library into the Python process using
|
|
||||||
``llvm.core.load_library_permanently`` and access it from Kaleidoscope
|
|
||||||
to produce simple output to the console:
|
|
||||||
|
|
||||||
>>> import llvm.core >>>
|
Now we can load this library into the Python process using
|
||||||
llvm.core.load_library_permanently('/home/max/llvmpy-tutorial/putchard.so')
|
``llvm.core.load_library_permanently`` and access it from Kaleidoscope
|
||||||
>>> import kaleidoscope >>> kaleidoscope.main() ready> extern
|
to produce simple output to the console::
|
||||||
putchard(x) Read an extern: declare double @putchard(double)
|
|
||||||
|
|
||||||
ready> putchard(65) + putchard(66) + putchard(67) + putchard(10) *ABC*
|
>>> import llvm.core
|
||||||
|
>>> llvm.core.load_library_permanently('/home/max/llvmpy-tutorial/putchard.so')
|
||||||
|
>>> import kaleidoscope
|
||||||
|
>>> kaleidoscope.main()
|
||||||
|
ready> extern putchard(x)
|
||||||
|
Read an extern:
|
||||||
|
declare double @putchard(double)
|
||||||
|
|
||||||
|
ready> putchard(65) + putchard(66) + putchard(67) + putchard(10)
|
||||||
|
*ABC*
|
||||||
Evaluated to: 0.0
|
Evaluated to: 0.0
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -446,14 +450,19 @@ the LLVM JIT and optimizer:
|
||||||
|
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import re from llvm.core import Module, Constant, Type, Function,
|
import re
|
||||||
Builder, FCMP_ULT from llvm.ee import ExecutionEngine, TargetData from
|
from llvm.core import Module, Constant, Type, Function, Builder, FCMP_ULT
|
||||||
llvm.passes import FunctionPassManager from llvm.passes import
|
from llvm.ee import ExecutionEngine, TargetData
|
||||||
(PASS_INSTRUCTION_COMBINING, PASS_REASSOCIATE, PASS_GVN,
|
from llvm.passes import FunctionPassManager
|
||||||
|
from llvm.passes import (PASS_INSTRUCTION_COMBINING,
|
||||||
|
PASS_REASSOCIATE,
|
||||||
|
PASS_GVN,
|
||||||
PASS_CFG_SIMPLIFICATION)
|
PASS_CFG_SIMPLIFICATION)
|
||||||
|
|
||||||
Globals
|
Globals
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
# The LLVM module, which holds all the IR code.
|
# The LLVM module, which holds all the IR code.
|
||||||
g_llvm_module = Module.new('my cool jit')
|
g_llvm_module = Module.new('my cool jit')
|
||||||
|
|
@ -471,35 +480,48 @@ the LLVM JIT and optimizer:
|
||||||
# The LLVM execution engine.
|
# The LLVM execution engine.
|
||||||
g_llvm_executor = ExecutionEngine.new(g_llvm_module)
|
g_llvm_executor = ExecutionEngine.new(g_llvm_module)
|
||||||
|
|
||||||
Lexer
|
Lexer
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
# The lexer yields one of these types for each token.
|
# The lexer yields one of these types for each token.
|
||||||
class EOFToken(object): pass
|
class EOFToken(object):
|
||||||
|
pass
|
||||||
|
|
||||||
class DefToken(object): pass
|
class DefToken(object):
|
||||||
|
pass
|
||||||
|
|
||||||
class ExternToken(object): pass
|
class ExternToken(object):
|
||||||
|
pass
|
||||||
|
|
||||||
class IdentifierToken(object): def __init__(self, name): self.name =
|
class IdentifierToken(object):
|
||||||
name
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
class NumberToken(object): def __init__(self, value): self.value =
|
class NumberToken(object):
|
||||||
value
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
class CharacterToken(object): def __init__(self, char): self.char =
|
class CharacterToken(object):
|
||||||
char def __eq__(self, other): return isinstance(other, CharacterToken)
|
def __init__(self, char):
|
||||||
and self.char == other.char def __ne__(self, other): return not self
|
self.char = char
|
||||||
== other
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, CharacterToken) and self.char == other.char
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self == other
|
||||||
|
|
||||||
# Regular expressions that tokens and comments of our language.
|
# Regular expressions that tokens and comments of our language.
|
||||||
REGEX_NUMBER = re.compile('[0-9]+(?:.[0-9]+)?') REGEX_IDENTIFIER =
|
REGEX_NUMBER = re.compile('[0-9]+(?:.[0-9]+)?')
|
||||||
re.compile('[a-zA-Z][a-zA-Z0-9]\ *') REGEX_COMMENT = re.compile('#.*')
|
REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]\ *')
|
||||||
|
REGEX_COMMENT = re.compile('#.*')
|
||||||
|
|
||||||
def Tokenize(string): while string: # Skip whitespace. if
|
def Tokenize(string):
|
||||||
string[0].isspace(): string = string[1:] continue
|
while string:
|
||||||
|
# Skip whitespace.
|
||||||
::
|
if string[0].isspace():
|
||||||
|
string = string[1:]
|
||||||
|
continue
|
||||||
|
|
||||||
# Run regexes.
|
# Run regexes.
|
||||||
comment_match = REGEX_COMMENT.match(string)
|
comment_match = REGEX_COMMENT.match(string)
|
||||||
|
|
@ -531,38 +553,47 @@ the LLVM JIT and optimizer:
|
||||||
|
|
||||||
yield EOFToken()
|
yield EOFToken()
|
||||||
|
|
||||||
Abstract Syntax Tree (aka Parse Tree)
|
Abstract Syntax Tree (aka Parse Tree)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
# Base class for all expression nodes.
|
# Base class for all expression nodes.
|
||||||
class ExpressionNode(object): pass
|
class ExpressionNode(object):
|
||||||
|
pass
|
||||||
|
|
||||||
# Expression class for numeric literals like "1.0".
|
# Expression class for numeric literals like "1.0".
|
||||||
class NumberExpressionNode(ExpressionNode):
|
class NumberExpressionNode(ExpressionNode):
|
||||||
|
|
||||||
def __init__(self, value): self.value = value
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
def CodeGen(self): return Constant.real(Type.double(), self.value)
|
def CodeGen(self):
|
||||||
|
return Constant.real(Type.double(), self.value)
|
||||||
|
|
||||||
# Expression class for referencing a variable, like "a".
|
# Expression class for referencing a variable, like "a".
|
||||||
class VariableExpressionNode(ExpressionNode):
|
class VariableExpressionNode(ExpressionNode):
|
||||||
|
|
||||||
def __init__(self, name): self.name = name
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
def CodeGen(self): if self.name in g_named_values: return
|
def CodeGen(self):
|
||||||
g_named_values[self.name] else: raise RuntimeError('Unknown variable
|
if self.name in g_named_values:
|
||||||
name: ' + self.name)
|
return g_named_values[self.name]
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Unknown variable name: ' + self.name)
|
||||||
|
|
||||||
# Expression class for a binary operator.
|
# Expression class for a binary operator.
|
||||||
class BinaryOperatorExpressionNode(ExpressionNode):
|
class BinaryOperatorExpressionNode(ExpressionNode):
|
||||||
|
|
||||||
def __init__(self, operator, left, right): self.operator = operator
|
def __init__(self, operator, left, right):
|
||||||
self.left = left self.right = right
|
self.operator = operator
|
||||||
|
self.left = left
|
||||||
|
self.right = right
|
||||||
|
|
||||||
def CodeGen(self): left = self.left.CodeGen() right =
|
def CodeGen(self):
|
||||||
self.right.CodeGen()
|
left = self.left.CodeGen()
|
||||||
|
right = self.right.CodeGen()
|
||||||
::
|
|
||||||
|
|
||||||
if self.operator == '+':
|
if self.operator == '+':
|
||||||
return g_llvm_builder.fadd(left, right, 'addtmp')
|
return g_llvm_builder.fadd(left, right, 'addtmp')
|
||||||
|
|
@ -580,13 +611,13 @@ the LLVM JIT and optimizer:
|
||||||
# Expression class for function calls.
|
# Expression class for function calls.
|
||||||
class CallExpressionNode(ExpressionNode):
|
class CallExpressionNode(ExpressionNode):
|
||||||
|
|
||||||
def __init__(self, callee, args): self.callee = callee self.args =
|
def __init__(self, callee, args):
|
||||||
args
|
self.callee = callee
|
||||||
|
self.args = args
|
||||||
|
|
||||||
def CodeGen(self): # Look up the name in the global module table. callee
|
def CodeGen(self):
|
||||||
= g_llvm_module.get_function_named(self.callee)
|
# Look up the name in the global module table.
|
||||||
|
callee = g_llvm_module.get_function_named(self.callee)
|
||||||
::
|
|
||||||
|
|
||||||
# Check for argument mismatch error.
|
# Check for argument mismatch error.
|
||||||
if len(callee.args) != len(self.args):
|
if len(callee.args) != len(self.args):
|
||||||
|
|
@ -601,13 +632,14 @@ the LLVM JIT and optimizer:
|
||||||
# takes).
|
# takes).
|
||||||
class PrototypeNode(object):
|
class PrototypeNode(object):
|
||||||
|
|
||||||
def __init__(self, name, args): self.name = name self.args = args
|
def __init__(self, name, args):
|
||||||
|
self.name = name
|
||||||
|
self.args = args
|
||||||
|
|
||||||
def CodeGen(self): # Make the function type, eg. double(double,double).
|
def CodeGen(self):
|
||||||
funct_type = Type.function( Type.double(), [Type.double()] \*
|
# Make the function type, eg. double(double,double).
|
||||||
len(self.args), False)
|
funct_type = Type.function(
|
||||||
|
Type.double(), [Type.double()] * len(self.args), False)
|
||||||
::
|
|
||||||
|
|
||||||
function = Function.new(g_llvm_module, funct_type, self.name)
|
function = Function.new(g_llvm_module, funct_type, self.name)
|
||||||
|
|
||||||
|
|
@ -637,12 +669,13 @@ the LLVM JIT and optimizer:
|
||||||
# This class represents a function definition itself.
|
# This class represents a function definition itself.
|
||||||
class FunctionNode(object):
|
class FunctionNode(object):
|
||||||
|
|
||||||
def __init__(self, prototype, body): self.prototype = prototype
|
def __init__(self, prototype, body):
|
||||||
|
self.prototype = prototype
|
||||||
self.body = body
|
self.body = body
|
||||||
|
|
||||||
def CodeGen(self): # Clear scope. g_named_values.clear()
|
def CodeGen(self):
|
||||||
|
# Clear scope.
|
||||||
::
|
g_named_values.clear()
|
||||||
|
|
||||||
# Create a function object.
|
# Create a function object.
|
||||||
function = self.prototype.CodeGen()
|
function = self.prototype.CodeGen()
|
||||||
|
|
@ -668,30 +701,37 @@ the LLVM JIT and optimizer:
|
||||||
|
|
||||||
return function
|
return function
|
||||||
|
|
||||||
Parser
|
Parser
|
||||||
------
|
------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
class Parser(object):
|
class Parser(object):
|
||||||
|
|
||||||
def __init__(self, tokens, binop_precedence): self.tokens = tokens
|
def __init__(self, tokens, binop_precedence):
|
||||||
self.binop_precedence = binop_precedence self.Next()
|
self.tokens = tokens
|
||||||
|
self.binop_precedence = binop_precedence
|
||||||
|
self.Next()
|
||||||
|
|
||||||
# Provide a simple token buffer. Parser.current is the current token the
|
# Provide a simple token buffer. Parser.current is the current token the
|
||||||
# parser is looking at. Parser.Next() reads another token from the lexer
|
# parser is looking at. Parser.Next() reads another token from the lexer and
|
||||||
and # updates Parser.current with its results. def Next(self):
|
# updates Parser.current with its results.
|
||||||
|
def Next(self):
|
||||||
self.current = self.tokens.next()
|
self.current = self.tokens.next()
|
||||||
|
|
||||||
# Gets the precedence of the current token, or -1 if the token is not a
|
# Gets the precedence of the current token, or -1 if the token is not a
|
||||||
binary # operator. def GetCurrentTokenPrecedence(self): if
|
binary # operator.
|
||||||
isinstance(self.current, CharacterToken): return
|
def GetCurrentTokenPrecedence(self):
|
||||||
self.binop_precedence.get(self.current.char, -1) else: return -1
|
if isinstance(self.current, CharacterToken):
|
||||||
|
return self.binop_precedence.get(self.current.char, -1)
|
||||||
|
else:
|
||||||
|
return -1
|
||||||
|
|
||||||
# identifierexpr ::= identifier \| identifier '(' expression\* ')' def
|
# identifierexpr ::= identifier | identifier '(' expression* ')'
|
||||||
ParseIdentifierExpr(self): identifier_name = self.current.name
|
def ParseIdentifierExpr(self):
|
||||||
|
identifier_name = self.current.name
|
||||||
self.Next() # eat identifier.
|
self.Next() # eat identifier.
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
if self.current != CharacterToken('('): # Simple variable reference.
|
if self.current != CharacterToken('('): # Simple variable reference.
|
||||||
return VariableExpressionNode(identifier_name)
|
return VariableExpressionNode(identifier_name)
|
||||||
|
|
||||||
|
|
@ -710,14 +750,15 @@ the LLVM JIT and optimizer:
|
||||||
self.Next() # eat ')'.
|
self.Next() # eat ')'.
|
||||||
return CallExpressionNode(identifier_name, args)
|
return CallExpressionNode(identifier_name, args)
|
||||||
|
|
||||||
# numberexpr ::= number def ParseNumberExpr(self): result =
|
# numberexpr ::= number
|
||||||
NumberExpressionNode(self.current.value) self.Next() # consume the
|
def ParseNumberExpr(self):
|
||||||
number. return result
|
result = NumberExpressionNode(self.current.value)
|
||||||
|
self.Next() # consume the number.
|
||||||
|
return result
|
||||||
|
|
||||||
# parenexpr ::= '(' expression ')' def ParseParenExpr(self): self.Next()
|
# parenexpr ::= '(' expression ')'
|
||||||
# eat '('.
|
def ParseParenExpr(self):
|
||||||
|
self.Next() # eat '('.
|
||||||
::
|
|
||||||
|
|
||||||
contents = self.ParseExpression()
|
contents = self.ParseExpression()
|
||||||
|
|
||||||
|
|
@ -727,18 +768,21 @@ the LLVM JIT and optimizer:
|
||||||
|
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
# primary ::= identifierexpr \| numberexpr \| parenexpr def
|
# primary ::= identifierexpr | numberexpr | parenexpr
|
||||||
ParsePrimary(self): if isinstance(self.current, IdentifierToken): return
|
def ParsePrimary(self):
|
||||||
self.ParseIdentifierExpr() elif isinstance(self.current, NumberToken):
|
if isinstance(self.current, IdentifierToken):
|
||||||
return self.ParseNumberExpr() elif self.current == CharacterToken('('):
|
return self.ParseIdentifierExpr()
|
||||||
return self.ParseParenExpr() else: raise RuntimeError('Unknown token
|
elif isinstance(self.current, NumberToken):
|
||||||
when expecting an expression.')
|
return self.ParseNumberExpr()
|
||||||
|
elif self.current == CharacterToken('('):
|
||||||
|
return self.ParseParenExpr()
|
||||||
|
else: raise RuntimeError('Unknown token when expecting an expression.')
|
||||||
|
|
||||||
# binoprhs ::= (operator primary)\* def ParseBinOpRHS(self, left,
|
# binoprhs ::= (operator primary)*
|
||||||
left_precedence): # If this is a binary operator, find its precedence.
|
def ParseBinOpRHS(self, left, left_precedence):
|
||||||
while True: precedence = self.GetCurrentTokenPrecedence()
|
# If this is a binary operator, find its precedence.
|
||||||
|
while True:
|
||||||
::
|
precedence = self.GetCurrentTokenPrecedence()
|
||||||
|
|
||||||
# If this is a binary operator that binds at least as tightly as the
|
# If this is a binary operator that binds at least as tightly as the
|
||||||
# current one, consume it; otherwise we are done.
|
# current one, consume it; otherwise we are done.
|
||||||
|
|
@ -760,14 +804,15 @@ the LLVM JIT and optimizer:
|
||||||
# Merge left/right.
|
# Merge left/right.
|
||||||
left = BinaryOperatorExpressionNode(binary_operator, left, right)
|
left = BinaryOperatorExpressionNode(binary_operator, left, right)
|
||||||
|
|
||||||
# expression ::= primary binoprhs def ParseExpression(self): left =
|
# expression ::= primary binoprhs
|
||||||
self.ParsePrimary() return self.ParseBinOpRHS(left, 0)
|
def ParseExpression(self):
|
||||||
|
left = self.ParsePrimary()
|
||||||
|
return self.ParseBinOpRHS(left, 0)
|
||||||
|
|
||||||
# prototype ::= id '(' id\* ')' def ParsePrototype(self): if not
|
# prototype ::= id '(' id* ')'
|
||||||
isinstance(self.current, IdentifierToken): raise RuntimeError('Expected
|
def ParsePrototype(self):
|
||||||
function name in prototype.')
|
if not isinstance(self.current, IdentifierToken):
|
||||||
|
raise RuntimeError('Expected function name in prototype.')
|
||||||
::
|
|
||||||
|
|
||||||
function_name = self.current.name
|
function_name = self.current.name
|
||||||
self.Next() # eat function name.
|
self.Next() # eat function name.
|
||||||
|
|
@ -789,54 +834,88 @@ the LLVM JIT and optimizer:
|
||||||
|
|
||||||
return PrototypeNode(function_name, arg_names)
|
return PrototypeNode(function_name, arg_names)
|
||||||
|
|
||||||
# definition ::= 'def' prototype expression def ParseDefinition(self):
|
# definition ::= 'def' prototype expression
|
||||||
self.Next() # eat def. proto = self.ParsePrototype() body =
|
def ParseDefinition(self):
|
||||||
self.ParseExpression() return FunctionNode(proto, body)
|
self.Next() # eat def.
|
||||||
|
proto = self.ParsePrototype()
|
||||||
|
body = self.ParseExpression()
|
||||||
|
return FunctionNode(proto, body)
|
||||||
|
|
||||||
# toplevelexpr ::= expression def ParseTopLevelExpr(self): proto =
|
# toplevelexpr ::= expression
|
||||||
PrototypeNode('', []) return FunctionNode(proto, self.ParseExpression())
|
def ParseTopLevelExpr(self):
|
||||||
|
proto = PrototypeNode('', [])
|
||||||
|
return FunctionNode(proto, self.ParseExpression())
|
||||||
|
|
||||||
# external ::= 'extern' prototype def ParseExtern(self): self.Next() #
|
# external ::= 'extern' prototype
|
||||||
eat extern. return self.ParsePrototype()
|
def ParseExtern(self):
|
||||||
|
self.Next() # eat extern.
|
||||||
|
return self.ParsePrototype()
|
||||||
|
|
||||||
# Top-Level parsing def HandleDefinition(self):
|
# Top-Level parsing
|
||||||
|
def HandleDefinition(self):
|
||||||
self.Handle(self.ParseDefinition, 'Read a function definition:')
|
self.Handle(self.ParseDefinition, 'Read a function definition:')
|
||||||
|
|
||||||
def HandleExtern(self): self.Handle(self.ParseExtern, 'Read an extern:')
|
def HandleExtern(self):
|
||||||
|
self.Handle(self.ParseExtern, 'Read an extern:')
|
||||||
|
|
||||||
def HandleTopLevelExpression(self): try: function =
|
def HandleTopLevelExpression(self):
|
||||||
self.ParseTopLevelExpr().CodeGen() result =
|
try:
|
||||||
g_llvm_executor.run_function(function, []) print 'Evaluated to:',
|
function = self.ParseTopLevelExpr().CodeGen()
|
||||||
result.as_real(Type.double()) except Exception, e: print 'Error:', e
|
result = g_llvm_executor.run_function(function, [])
|
||||||
try: self.Next() # Skip for error recovery. except: pass
|
print 'Evaluated to:', result.as_real(Type.double())
|
||||||
|
except Exception, e:
|
||||||
|
print 'Error:', e
|
||||||
|
try:
|
||||||
|
self.Next() # Skip for error recovery.
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def Handle(self, function, message): try: print message,
|
def Handle(self, function, message):
|
||||||
function().CodeGen() except Exception, e: print 'Error:', e try:
|
try:
|
||||||
self.Next() # Skip for error recovery. except: pass
|
print message, function().CodeGen()
|
||||||
|
except Exception, e:
|
||||||
|
print 'Error:', e
|
||||||
|
try:
|
||||||
|
self.Next() # Skip for error recovery.
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
Main driver code.
|
Main driver code.
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
def main(): # Set up the optimizer pipeline. Start with registering info
|
.. code-block:: python
|
||||||
about how the # target lays out data structures.
|
|
||||||
g_llvm_pass_manager.add(g_llvm_executor.target_data) # Do simple
|
def main():
|
||||||
"peephole" optimizations and bit-twiddling optzns.
|
# Set up the optimizer pipeline. Start with registering info about how the
|
||||||
g_llvm_pass_manager.add(PASS_INSTRUCTION_COMBINING) # Reassociate
|
# target lays out data structures.
|
||||||
expressions. g_llvm_pass_manager.add(PASS_REASSOCIATE) # Eliminate
|
g_llvm_pass_manager.add(g_llvm_executor.target_data)
|
||||||
Common SubExpressions. g_llvm_pass_manager.add(PASS_GVN) # Simplify
|
# Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||||
the control flow graph (deleting unreachable blocks, etc).
|
g_llvm_pass_manager.add(PASS_INSTRUCTION_COMBINING)
|
||||||
|
# Reassociate expressions.
|
||||||
|
g_llvm_pass_manager.add(PASS_REASSOCIATE)
|
||||||
|
# Eliminate Common SubExpressions.
|
||||||
|
g_llvm_pass_manager.add(PASS_GVN)
|
||||||
|
# Simplify the control flow graph (deleting unreachable blocks, etc).
|
||||||
g_llvm_pass_manager.add(PASS_CFG_SIMPLIFICATION)
|
g_llvm_pass_manager.add(PASS_CFG_SIMPLIFICATION)
|
||||||
|
|
||||||
g_llvm_pass_manager.initialize()
|
g_llvm_pass_manager.initialize()
|
||||||
|
|
||||||
# Install standard binary operators. # 1 is lowest possible precedence.
|
# Install standard binary operators.
|
||||||
40 is the highest. operator_precedence = { '<': 10, '+': 20, '-': 20,
|
# 1 is lowest possible precedence. 40 is the highest.
|
||||||
'\*': 40 }
|
operator_precedence = {
|
||||||
|
'<': 10,
|
||||||
|
'+': 20,
|
||||||
|
'-': 20,
|
||||||
|
'\*': 40
|
||||||
|
}
|
||||||
|
|
||||||
# Run the main "interpreter loop". while True: print 'ready>', try: raw
|
# Run the main "interpreter loop".
|
||||||
= raw_input() except KeyboardInterrupt: break
|
while True:
|
||||||
|
print 'ready>',
|
||||||
::
|
try:
|
||||||
|
raw = raw_input()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
|
||||||
parser = Parser(Tokenize(raw), operator_precedence)
|
parser = Parser(Tokenize(raw), operator_precedence)
|
||||||
while True:
|
while True:
|
||||||
|
|
@ -850,6 +929,8 @@ the LLVM JIT and optimizer:
|
||||||
else:
|
else:
|
||||||
parser.HandleTopLevelExpression()
|
parser.HandleTopLevelExpression()
|
||||||
|
|
||||||
# Print out all of the generated code. print '', g_llvm_module
|
# Print out all of the generated code.
|
||||||
|
print '', g_llvm_module
|
||||||
|
|
||||||
if **name** == '__main__': main()
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue