Doc editing

This commit is contained in:
Maggie Mari 2012-08-20 17:52:00 -05:00
commit e7cbaea1e8

View file

@ -933,171 +933,183 @@ Abstract Syntax Tree (aka Parse Tree)
self.left = left self.left = left
self.right = right self.right = right
def CodeGen(self): left = self.left.CodeGen() def CodeGen(self):
right = 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')
elif self.operator == '-': elif self.operator == '-':
return g_llvm_builder.fsub(left, right, 'subtmp') return g_llvm_builder.fsub(left, right, 'subtmp')
elif self.operator == '*': elif self.operator == '*':
return g_llvm_builder.fmul(left, right, 'multmp') return g_llvm_builder.fmul(left, right, 'multmp')
elif self.operator == '<': elif self.operator == '<':
result = g_llvm_builder.fcmp(FCMP_ULT, left, right, 'cmptmp') result = g_llvm_builder.fcmp(FCMP_ULT, left, right, 'cmptmp')
# Convert bool 0 or 1 to double 0.0 or 1.0. # Convert bool 0 or 1 to double 0.0 or 1.0.
return g_llvm_builder.uitofp(result, Type.double(), 'booltmp') return g_llvm_builder.uitofp(result, Type.double(), 'booltmp')
else: else:
function = g_llvm_module.get_function_named('binary' + self.operator) function = g_llvm_module.get_function_named('binary' + self.operator)
return g_llvm_builder.call(function, [left, right], 'binop') return g_llvm_builder.call(function, [left, right], 'binop')
# 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
= g_llvm_module.get_function_named(self.callee) def CodeGen(self):
# 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):
raise RuntimeError('Incorrect number of arguments passed.') raise RuntimeError('Incorrect number of arguments passed.')
arg_values = [i.CodeGen() for i in self.args] arg_values = [i.CodeGen() for i in self.args]
return g_llvm_builder.call(callee, arg_values, 'calltmp') return g_llvm_builder.call(callee, arg_values, 'calltmp')
# Expression class for if/then/else. # Expression class for if/then/else.
class IfExpressionNode(ExpressionNode): class IfExpressionNode(ExpressionNode):
def __init__(self, condition, then_branch, else_branch): def __init__(self, condition, then_branch, else_branch):
self.condition = condition self.then_branch = then_branch self.condition = condition
self.else_branch = else_branch self.then_branch = then_branch
self.else_branch = else_branch
def CodeGen(self): condition = self.condition.CodeGen()
def CodeGen(self): condition = self.condition.CodeGen()
::
# Convert condition to a bool by comparing equal to 0.0.
# Convert condition to a bool by comparing equal to 0.0. condition_bool = g_llvm_builder.fcmp(
condition_bool = g_llvm_builder.fcmp( FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcond')
FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcond')
function = g_llvm_builder.basic_block.function
function = g_llvm_builder.basic_block.function
# Create blocks for the then and else cases. Insert the 'then' block at the
# Create blocks for the then and else cases. Insert the 'then' block at the # end of the function.
# end of the function. then_block = function.append_basic_block('then')
then_block = function.append_basic_block('then') else_block = function.append_basic_block('else')
else_block = function.append_basic_block('else') merge_block = function.append_basic_block('ifcond')
merge_block = function.append_basic_block('ifcond')
g_llvm_builder.cbranch(condition_bool, then_block, else_block)
g_llvm_builder.cbranch(condition_bool, then_block, else_block)
# Emit then value.
# Emit then value. g_llvm_builder.position_at_end(then_block)
g_llvm_builder.position_at_end(then_block) then_value = self.then_branch.CodeGen()
then_value = self.then_branch.CodeGen() g_llvm_builder.branch(merge_block)
g_llvm_builder.branch(merge_block)
# Codegen of 'Then' can change the current block; update then_block for the
# Codegen of 'Then' can change the current block; update then_block for the # PHI node.
# PHI node. then_block = g_llvm_builder.basic_block
then_block = g_llvm_builder.basic_block
# Emit else block.
# Emit else block. g_llvm_builder.position_at_end(else_block)
g_llvm_builder.position_at_end(else_block) else_value = self.else_branch.CodeGen()
else_value = self.else_branch.CodeGen() g_llvm_builder.branch(merge_block)
g_llvm_builder.branch(merge_block)
# Codegen of 'Else' can change the current block, update else_block for the
# Codegen of 'Else' can change the current block, update else_block for the # PHI node.
# PHI node. else_block = g_llvm_builder.basic_block
else_block = g_llvm_builder.basic_block
# Emit merge block.
# Emit merge block. g_llvm_builder.position_at_end(merge_block)
g_llvm_builder.position_at_end(merge_block) phi = g_llvm_builder.phi(Type.double(), 'iftmp')
phi = g_llvm_builder.phi(Type.double(), 'iftmp') phi.add_incoming(then_value, then_block)
phi.add_incoming(then_value, then_block) phi.add_incoming(else_value, else_block)
phi.add_incoming(else_value, else_block)
return phi
return phi
# Expression class for for/in. # Expression class for for/in.
class ForExpressionNode(ExpressionNode): class ForExpressionNode(ExpressionNode):
def __init__(self, loop_variable, start, end, step, body): def __init__(self, loop_variable, start, end, step, body):
self.loop_variable = loop_variable self.start = start self.end = end self.loop_variable = loop_variable
self.step = step self.body = body self.start = start
self.end = end
def CodeGen(self): # Output this as: # ... # start = startexpr # goto self.step = step
loop # loop: # variable = phi [start, loopheader], [nextvariable, self.body = body
loopend] # ... # bodyexpr # ... # loopend: # step = stepexpr #
nextvariable = variable + step # endcond = endexpr # br endcond, loop, def CodeGen(self):
endloop # outloop: # Output this as:
# ...
:: # start = startexpr
# goto loop
# Emit the start code first, without 'variable' in scope. # loop:
start_value = self.start.CodeGen() # variable = phi [start, loopheader], [nextvariable, loopend]
# ...
# Make the new basic block for the loop header, inserting after current # bodyexpr
# block. # ...
function = g_llvm_builder.basic_block.function # loopend:
pre_header_block = g_llvm_builder.basic_block # step = stepexpr
loop_block = function.append_basic_block('loop') # nextvariable = variable + step
# endcond = endexpr
# Insert an explicit fallthrough from the current block to the loop_block. # br endcond, loop, endloop
g_llvm_builder.branch(loop_block) # outloop:
# Start insertion in loop_block. # Emit the start code first, without 'variable' in scope.
g_llvm_builder.position_at_end(loop_block) start_value = self.start.CodeGen()
# Start the PHI node with an entry for start. # Make the new basic block for the loop header, inserting after current
variable_phi = g_llvm_builder.phi(Type.double(), self.loop_variable) # block.
variable_phi.add_incoming(start_value, pre_header_block) function = g_llvm_builder.basic_block.function
pre_header_block = g_llvm_builder.basic_block
# Within the loop, the variable is defined equal to the PHI node. If it loop_block = function.append_basic_block('loop')
# shadows an existing variable, we have to restore it, so save it now.
old_value = g_named_values.get(self.loop_variable, None) # Insert an explicit fallthrough from the current block to the loop_block.
g_named_values[self.loop_variable] = variable_phi g_llvm_builder.branch(loop_block)
# Emit the body of the loop. This, like any other expr, can change the # Start insertion in loop_block.
# current BB. Note that we ignore the value computed by the body. g_llvm_builder.position_at_end(loop_block)
self.body.CodeGen()
# Start the PHI node with an entry for start.
# Emit the step value. variable_phi = g_llvm_builder.phi(Type.double(), self.loop_variable)
if self.step: variable_phi.add_incoming(start_value, pre_header_block)
step_value = self.step.CodeGen()
else: # Within the loop, the variable is defined equal to the PHI node. If it
# If not specified, use 1.0. # shadows an existing variable, we have to restore it, so save it now.
step_value = Constant.real(Type.double(), 1) old_value = g_named_values.get(self.loop_variable, None)
g_named_values[self.loop_variable] = variable_phi
next_value = g_llvm_builder.fadd(variable_phi, step_value, 'next')
# Emit the body of the loop. This, like any other expr, can change the
# Compute the end condition and convert it to a bool by comparing to 0.0. # current BB. Note that we ignore the value computed by the body.
end_condition = self.end.CodeGen() self.body.CodeGen()
end_condition_bool = g_llvm_builder.fcmp(
FCMP_ONE, end_condition, Constant.real(Type.double(), 0), 'loopcond') # Emit the step value.
if self.step:
# Create the "after loop" block and insert it. step_value = self.step.CodeGen()
loop_end_block = g_llvm_builder.basic_block else:
after_block = function.append_basic_block('afterloop') # If not specified, use 1.0.
step_value = Constant.real(Type.double(), 1)
# Insert the conditional branch into the end of loop_end_block.
g_llvm_builder.cbranch(end_condition_bool, loop_block, after_block) next_value = g_llvm_builder.fadd(variable_phi, step_value, 'next')
# Any new code will be inserted in after_block. # Compute the end condition and convert it to a bool by comparing to 0.0.
g_llvm_builder.position_at_end(after_block) end_condition = self.end.CodeGen()
end_condition_bool = g_llvm_builder.fcmp(
# Add a new entry to the PHI node for the backedge. FCMP_ONE, end_condition, Constant.real(Type.double(), 0), 'loopcond')
variable_phi.add_incoming(next_value, loop_end_block)
# Create the "after loop" block and insert it.
# Restore the unshadowed variable. loop_end_block = g_llvm_builder.basic_block
if old_value: after_block = function.append_basic_block('afterloop')
g_named_values[self.loop_variable] = old_value
else: # Insert the conditional branch into the end of loop_end_block.
del g_named_values[self.loop_variable] g_llvm_builder.cbranch(end_condition_bool, loop_block, after_block)
# for expr always returns 0.0. # Any new code will be inserted in after_block.
return Constant.real(Type.double(), 0) g_llvm_builder.position_at_end(after_block)
# Add a new entry to the PHI node for the backedge.
variable_phi.add_incoming(next_value, loop_end_block)
# Restore the unshadowed variable.
if old_value:
g_named_values[self.loop_variable] = old_value
else:
del g_named_values[self.loop_variable]
# for expr always returns 0.0.
return Constant.real(Type.double(), 0)
# Expression class for a unary operator. # Expression class for a unary operator.
class UnaryExpressionNode(ExpressionNode): class UnaryExpressionNode(ExpressionNode):