Doc editing
This commit is contained in:
parent
c7cbebab7b
commit
e7cbaea1e8
1 changed files with 164 additions and 152 deletions
|
|
@ -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
|
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.
|
||||||
|
if len(callee.args) != len(self.args):
|
||||||
|
raise RuntimeError('Incorrect number of arguments passed.')
|
||||||
|
|
||||||
# Check for argument mismatch error.
|
arg_values = [i.CodeGen() for i in self.args]
|
||||||
if len(callee.args) != len(self.args):
|
|
||||||
raise RuntimeError('Incorrect number of arguments passed.')
|
|
||||||
|
|
||||||
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.
|
||||||
|
condition_bool = g_llvm_builder.fcmp(
|
||||||
|
FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcond')
|
||||||
|
|
||||||
# Convert condition to a bool by comparing equal to 0.0.
|
function = g_llvm_builder.basic_block.function
|
||||||
condition_bool = g_llvm_builder.fcmp(
|
|
||||||
FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcond')
|
|
||||||
|
|
||||||
function = g_llvm_builder.basic_block.function
|
# Create blocks for the then and else cases. Insert the 'then' block at the
|
||||||
|
# end of the function.
|
||||||
|
then_block = function.append_basic_block('then')
|
||||||
|
else_block = function.append_basic_block('else')
|
||||||
|
merge_block = function.append_basic_block('ifcond')
|
||||||
|
|
||||||
# Create blocks for the then and else cases. Insert the 'then' block at the
|
g_llvm_builder.cbranch(condition_bool, then_block, else_block)
|
||||||
# end of the function.
|
|
||||||
then_block = function.append_basic_block('then')
|
|
||||||
else_block = function.append_basic_block('else')
|
|
||||||
merge_block = function.append_basic_block('ifcond')
|
|
||||||
|
|
||||||
g_llvm_builder.cbranch(condition_bool, then_block, else_block)
|
# Emit then value.
|
||||||
|
g_llvm_builder.position_at_end(then_block)
|
||||||
|
then_value = self.then_branch.CodeGen()
|
||||||
|
g_llvm_builder.branch(merge_block)
|
||||||
|
|
||||||
# Emit then value.
|
# Codegen of 'Then' can change the current block; update then_block for the
|
||||||
g_llvm_builder.position_at_end(then_block)
|
# PHI node.
|
||||||
then_value = self.then_branch.CodeGen()
|
then_block = g_llvm_builder.basic_block
|
||||||
g_llvm_builder.branch(merge_block)
|
|
||||||
|
|
||||||
# Codegen of 'Then' can change the current block; update then_block for the
|
# Emit else block.
|
||||||
# PHI node.
|
g_llvm_builder.position_at_end(else_block)
|
||||||
then_block = g_llvm_builder.basic_block
|
else_value = self.else_branch.CodeGen()
|
||||||
|
g_llvm_builder.branch(merge_block)
|
||||||
|
|
||||||
# Emit else block.
|
# Codegen of 'Else' can change the current block, update else_block for the
|
||||||
g_llvm_builder.position_at_end(else_block)
|
# PHI node.
|
||||||
else_value = self.else_branch.CodeGen()
|
else_block = g_llvm_builder.basic_block
|
||||||
g_llvm_builder.branch(merge_block)
|
|
||||||
|
|
||||||
# Codegen of 'Else' can change the current block, update else_block for the
|
# Emit merge block.
|
||||||
# PHI node.
|
g_llvm_builder.position_at_end(merge_block)
|
||||||
else_block = g_llvm_builder.basic_block
|
phi = g_llvm_builder.phi(Type.double(), 'iftmp')
|
||||||
|
phi.add_incoming(then_value, then_block)
|
||||||
|
phi.add_incoming(else_value, else_block)
|
||||||
|
|
||||||
# Emit merge block.
|
return phi
|
||||||
g_llvm_builder.position_at_end(merge_block)
|
|
||||||
phi = g_llvm_builder.phi(Type.double(), 'iftmp')
|
|
||||||
phi.add_incoming(then_value, then_block)
|
|
||||||
phi.add_incoming(else_value, else_block)
|
|
||||||
|
|
||||||
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
|
||||||
|
self.step = step
|
||||||
|
self.body = body
|
||||||
|
|
||||||
def CodeGen(self): # Output this as: # ... # start = startexpr # goto
|
def CodeGen(self):
|
||||||
loop # loop: # variable = phi [start, loopheader], [nextvariable,
|
# Output this as:
|
||||||
loopend] # ... # bodyexpr # ... # loopend: # step = stepexpr #
|
# ...
|
||||||
nextvariable = variable + step # endcond = endexpr # br endcond, loop,
|
# start = startexpr
|
||||||
endloop # outloop:
|
# goto loop
|
||||||
|
# loop:
|
||||||
|
# variable = phi [start, loopheader], [nextvariable, loopend]
|
||||||
|
# ...
|
||||||
|
# bodyexpr
|
||||||
|
# ...
|
||||||
|
# loopend:
|
||||||
|
# step = stepexpr
|
||||||
|
# nextvariable = variable + step
|
||||||
|
# endcond = endexpr
|
||||||
|
# br endcond, loop, endloop
|
||||||
|
# outloop:
|
||||||
|
|
||||||
::
|
# Emit the start code first, without 'variable' in scope.
|
||||||
|
start_value = self.start.CodeGen()
|
||||||
|
|
||||||
# Emit the start code first, without 'variable' in scope.
|
# Make the new basic block for the loop header, inserting after current
|
||||||
start_value = self.start.CodeGen()
|
# block.
|
||||||
|
function = g_llvm_builder.basic_block.function
|
||||||
|
pre_header_block = g_llvm_builder.basic_block
|
||||||
|
loop_block = function.append_basic_block('loop')
|
||||||
|
|
||||||
# Make the new basic block for the loop header, inserting after current
|
# Insert an explicit fallthrough from the current block to the loop_block.
|
||||||
# block.
|
g_llvm_builder.branch(loop_block)
|
||||||
function = g_llvm_builder.basic_block.function
|
|
||||||
pre_header_block = g_llvm_builder.basic_block
|
|
||||||
loop_block = function.append_basic_block('loop')
|
|
||||||
|
|
||||||
# Insert an explicit fallthrough from the current block to the loop_block.
|
# Start insertion in loop_block.
|
||||||
g_llvm_builder.branch(loop_block)
|
g_llvm_builder.position_at_end(loop_block)
|
||||||
|
|
||||||
# Start insertion in loop_block.
|
# Start the PHI node with an entry for start.
|
||||||
g_llvm_builder.position_at_end(loop_block)
|
variable_phi = g_llvm_builder.phi(Type.double(), self.loop_variable)
|
||||||
|
variable_phi.add_incoming(start_value, pre_header_block)
|
||||||
|
|
||||||
# Start the PHI node with an entry for start.
|
# Within the loop, the variable is defined equal to the PHI node. If it
|
||||||
variable_phi = g_llvm_builder.phi(Type.double(), self.loop_variable)
|
# shadows an existing variable, we have to restore it, so save it now.
|
||||||
variable_phi.add_incoming(start_value, pre_header_block)
|
old_value = g_named_values.get(self.loop_variable, None)
|
||||||
|
g_named_values[self.loop_variable] = variable_phi
|
||||||
|
|
||||||
# Within the loop, the variable is defined equal to the PHI node. If it
|
# Emit the body of the loop. This, like any other expr, can change the
|
||||||
# shadows an existing variable, we have to restore it, so save it now.
|
# current BB. Note that we ignore the value computed by the body.
|
||||||
old_value = g_named_values.get(self.loop_variable, None)
|
self.body.CodeGen()
|
||||||
g_named_values[self.loop_variable] = variable_phi
|
|
||||||
|
|
||||||
# Emit the body of the loop. This, like any other expr, can change the
|
# Emit the step value.
|
||||||
# current BB. Note that we ignore the value computed by the body.
|
if self.step:
|
||||||
self.body.CodeGen()
|
step_value = self.step.CodeGen()
|
||||||
|
else:
|
||||||
|
# If not specified, use 1.0.
|
||||||
|
step_value = Constant.real(Type.double(), 1)
|
||||||
|
|
||||||
# Emit the step value.
|
next_value = g_llvm_builder.fadd(variable_phi, step_value, 'next')
|
||||||
if self.step:
|
|
||||||
step_value = self.step.CodeGen()
|
|
||||||
else:
|
|
||||||
# If not specified, use 1.0.
|
|
||||||
step_value = Constant.real(Type.double(), 1)
|
|
||||||
|
|
||||||
next_value = g_llvm_builder.fadd(variable_phi, step_value, 'next')
|
# Compute the end condition and convert it to a bool by comparing to 0.0.
|
||||||
|
end_condition = self.end.CodeGen()
|
||||||
|
end_condition_bool = g_llvm_builder.fcmp(
|
||||||
|
FCMP_ONE, end_condition, Constant.real(Type.double(), 0), 'loopcond')
|
||||||
|
|
||||||
# Compute the end condition and convert it to a bool by comparing to 0.0.
|
# Create the "after loop" block and insert it.
|
||||||
end_condition = self.end.CodeGen()
|
loop_end_block = g_llvm_builder.basic_block
|
||||||
end_condition_bool = g_llvm_builder.fcmp(
|
after_block = function.append_basic_block('afterloop')
|
||||||
FCMP_ONE, end_condition, Constant.real(Type.double(), 0), 'loopcond')
|
|
||||||
|
|
||||||
# Create the "after loop" block and insert it.
|
# Insert the conditional branch into the end of loop_end_block.
|
||||||
loop_end_block = g_llvm_builder.basic_block
|
g_llvm_builder.cbranch(end_condition_bool, loop_block, after_block)
|
||||||
after_block = function.append_basic_block('afterloop')
|
|
||||||
|
|
||||||
# Insert the conditional branch into the end of loop_end_block.
|
# Any new code will be inserted in after_block.
|
||||||
g_llvm_builder.cbranch(end_condition_bool, loop_block, after_block)
|
g_llvm_builder.position_at_end(after_block)
|
||||||
|
|
||||||
# Any new code will be inserted in after_block.
|
# Add a new entry to the PHI node for the backedge.
|
||||||
g_llvm_builder.position_at_end(after_block)
|
variable_phi.add_incoming(next_value, loop_end_block)
|
||||||
|
|
||||||
# Add a new entry to the PHI node for the backedge.
|
# Restore the unshadowed variable.
|
||||||
variable_phi.add_incoming(next_value, loop_end_block)
|
if old_value:
|
||||||
|
g_named_values[self.loop_variable] = old_value
|
||||||
|
else:
|
||||||
|
del g_named_values[self.loop_variable]
|
||||||
|
|
||||||
# Restore the unshadowed variable.
|
# for expr always returns 0.0.
|
||||||
if old_value:
|
return Constant.real(Type.double(), 0)
|
||||||
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):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue