compiler: significantly increase readability of LLVM and ARTIQ IRs.

This commit is contained in:
whitequark 2016-03-26 11:38:55 +00:00
parent 8d0566661a
commit 3ee9834197
3 changed files with 133 additions and 109 deletions

View File

@ -437,7 +437,7 @@ class Function:
def _add_name(self, base_name):
if base_name == "":
name = "v.{}".format(self.next_name)
name = "UNN.{}".format(self.next_name)
self.next_name += 1
elif base_name in self.names:
name = "{}.{}".format(base_name, self.next_name)
@ -869,9 +869,11 @@ class Builtin(Instruction):
"""
:param op: (string) operation name
"""
def __init__(self, op, operands, typ, name=""):
def __init__(self, op, operands, typ, name=None):
assert isinstance(op, str)
for operand in operands: assert isinstance(operand, Value)
if name is None:
name = "BLT.{}".format(op)
super().__init__(operands, typ, name)
self.op = op

View File

@ -237,25 +237,25 @@ class ARTIQIRGenerator(algorithm.Visitor):
for arg_name, default_node in zip(typ.optargs, node.args.defaults):
default = self.visit(default_node)
env_default_name = \
self.current_env.type.add("default$" + arg_name, default.type)
self.current_env.type.add("$default." + arg_name, default.type)
self.append(ir.SetLocal(self.current_env, env_default_name, default))
defaults.append(env_default_name)
old_name, self.name = self.name, self.name + [name]
env_arg = ir.EnvironmentArgument(self.current_env.type, "outerenv")
env_arg = ir.EnvironmentArgument(self.current_env.type, "CLS")
old_args, self.current_args = self.current_args, {}
args = []
for arg_name in typ.args:
arg = ir.Argument(typ.args[arg_name], "arg." + arg_name)
arg = ir.Argument(typ.args[arg_name], "ARG." + arg_name)
self.current_args[arg_name] = arg
args.append(arg)
optargs = []
for arg_name in typ.optargs:
arg = ir.Argument(ir.TOption(typ.optargs[arg_name]), "arg." + arg_name)
arg = ir.Argument(ir.TOption(typ.optargs[arg_name]), "ARG." + arg_name)
self.current_args[arg_name] = arg
optargs.append(arg)
@ -268,7 +268,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
if not is_lambda:
self.function_map[node] = func
entry = self.add_block()
entry = self.add_block("entry")
old_block, self.current_block = self.current_block, entry
old_globals, self.current_globals = self.current_globals, node.globals_in_scope
@ -279,13 +279,13 @@ class ARTIQIRGenerator(algorithm.Visitor):
if var not in node.globals_in_scope}
env_type = ir.TEnvironment(name=func.name,
vars=env_without_globals, outer=self.current_env.type)
env = self.append(ir.Alloc([], env_type, name="env"))
env = self.append(ir.Alloc([], env_type, name="ENV"))
old_env, self.current_env = self.current_env, env
if not is_lambda:
priv_env_type = ir.TEnvironment(name=func.name + ".priv",
priv_env_type = ir.TEnvironment(name="{}.private".format(func.name),
vars={ "$return": typ.ret })
priv_env = self.append(ir.Alloc([], priv_env_type, name="privenv"))
priv_env = self.append(ir.Alloc([], priv_env_type, name="PRV"))
old_priv_env, self.current_private_env = self.current_private_env, priv_env
self.append(ir.SetLocal(env, "$outer", env_arg))
@ -401,18 +401,18 @@ class ARTIQIRGenerator(algorithm.Visitor):
cond = self.coerce_to_bool(cond)
head = self.current_block
if_true = self.add_block()
if_true = self.add_block("if.body")
self.current_block = if_true
self.visit(node.body)
post_if_true = self.current_block
if any(node.orelse):
if_false = self.add_block()
if_false = self.add_block("if.else")
self.current_block = if_false
self.visit(node.orelse)
post_if_false = self.current_block
tail = self.add_block()
tail = self.add_block("if.tail")
self.current_block = tail
if not post_if_true.is_terminated():
post_if_true.append(ir.Branch(tail))
@ -499,9 +499,9 @@ class ARTIQIRGenerator(algorithm.Visitor):
head = self.add_block("for.head")
self.append(ir.Branch(head))
self.current_block = head
phi = self.append(ir.Phi(length.type))
phi = self.append(ir.Phi(length.type, name="IND"))
phi.add_incoming(ir.Constant(0, phi.type), prehead)
cond = self.append(ir.Compare(ast.Lt(loc=None), phi, length))
cond = self.append(ir.Compare(ast.Lt(loc=None), phi, length, name="CMP"))
break_block = self.add_block("for.break")
old_break, self.break_target = self.break_target, break_block
@ -510,7 +510,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
old_continue, self.continue_target = self.continue_target, continue_block
self.current_block = continue_block
updated_index = self.append(ir.Arith(ast.Add(loc=None), phi, ir.Constant(1, phi.type)))
updated_index = self.append(ir.Arith(ast.Add(loc=None), phi, ir.Constant(1, phi.type),
name="IND.new"))
phi.add_incoming(updated_index, continue_block)
self.append(ir.Branch(head))
@ -597,13 +598,13 @@ class ARTIQIRGenerator(algorithm.Visitor):
# k for continuation
final_suffix = ".try@{}:{}".format(node.loc.line(), node.loc.column())
final_env_type = ir.TEnvironment(name=self.current_function.name + final_suffix,
vars={ "$k": ir.TBasicBlock() })
vars={ "$cont": ir.TBasicBlock() })
final_state = self.append(ir.Alloc([], final_env_type))
final_targets = []
final_paths = []
def final_branch(target, block):
block.append(ir.SetLocal(final_state, "$k", target))
block.append(ir.SetLocal(final_state, "$cont", target))
final_targets.append(target)
final_paths.append(block)
@ -696,19 +697,19 @@ class ARTIQIRGenerator(algorithm.Visitor):
block.append(ir.Branch(finalizer))
if not body.is_terminated():
body.append(ir.SetLocal(final_state, "$k", tail))
body.append(ir.SetLocal(final_state, "$cont", tail))
body.append(ir.Branch(finalizer))
cleanup.append(ir.SetLocal(final_state, "$k", reraise))
cleanup.append(ir.SetLocal(final_state, "$cont", reraise))
cleanup.append(ir.Branch(finalizer))
for handler, post_handler in handlers:
if not post_handler.is_terminated():
post_handler.append(ir.SetLocal(final_state, "$k", tail))
post_handler.append(ir.SetLocal(final_state, "$cont", tail))
post_handler.append(ir.Branch(finalizer))
if not post_finalizer.is_terminated():
dest = post_finalizer.append(ir.GetLocal(final_state, "$k"))
dest = post_finalizer.append(ir.GetLocal(final_state, "$cont"))
post_finalizer.append(ir.IndirectBranch(dest, final_targets))
else:
if not body.is_terminated():
@ -753,7 +754,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
heads, tails = [], []
for stmt in node.body:
self.current_block = self.add_block()
self.current_block = self.add_block("interleave.branch")
heads.append(self.current_block)
self.visit(stmt)
tails.append(self.current_block)
@ -761,7 +762,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
for head in heads:
interleave.add_destination(head)
self.current_block = self.add_block()
self.current_block = self.add_block("interleave.tail")
for tail in tails:
if not tail.is_terminated():
tail.append(ir.Branch(self.current_block))
@ -773,7 +774,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
for stmt in node.body:
self.append(ir.Builtin("at_mu", [start_mu], builtins.TNone()))
block = self.add_block()
block = self.add_block("parallel.branch")
if self.current_block.is_terminated():
self.warn_unreachable(stmt[0])
else:
@ -837,17 +838,17 @@ class ARTIQIRGenerator(algorithm.Visitor):
cond = self.visit(node.test)
head = self.current_block
if_true = self.add_block()
if_true = self.add_block("ifexp.body")
self.current_block = if_true
true_result = self.visit(node.body)
post_if_true = self.current_block
if_false = self.add_block()
if_false = self.add_block("ifexp.else")
self.current_block = if_false
false_result = self.visit(node.orelse)
post_if_false = self.current_block
tail = self.add_block()
tail = self.add_block("ifexp.tail")
self.current_block = tail
if not post_if_true.is_terminated():
@ -881,10 +882,10 @@ class ARTIQIRGenerator(algorithm.Visitor):
if self.current_class is not None and \
name in self.current_class.type.attributes:
return self.append(ir.GetAttr(self.current_class, name,
name="local." + name))
name="FLD." + name))
return self.append(ir.GetLocal(self._env_for(name), name,
name="local." + name))
name="LOC." + name))
def _set_local(self, name, value):
if self.current_class is not None and \
@ -910,7 +911,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
if self.current_assign is None:
return self.append(ir.GetAttr(obj, node.attr,
name="{}.{}".format(_readable_name(obj), node.attr)))
name="{}.FLD.{}".format(_readable_name(obj), node.attr)))
elif types.is_rpc_function(self.current_assign.type):
# RPC functions are just type-level markers
return self.append(ir.Builtin("nop", [], builtins.TNone()))
@ -930,47 +931,47 @@ class ARTIQIRGenerator(algorithm.Visitor):
ir.Constant(False, builtins.TBool())))
head = self.current_block
self.current_block = out_of_bounds_block = self.add_block()
self.current_block = out_of_bounds_block = self.add_block("index.outofbounds")
exn = self.alloc_exn(builtins.TException("IndexError"),
ir.Constant("index {0} out of bounds 0:{1}", builtins.TStr()),
index, length)
self.raise_exn(exn, loc=loc)
self.current_block = in_bounds_block = self.add_block()
self.current_block = in_bounds_block = self.add_block("index.inbounds")
head.append(ir.BranchIf(in_bounds, in_bounds_block, out_of_bounds_block))
return mapped_index
def _make_check(self, cond, exn_gen, loc=None):
def _make_check(self, cond, exn_gen, loc=None, name="check"):
# cond: bool Value, condition
# exn_gen: lambda()->exn Value, exception if condition not true
cond_block = self.current_block
self.current_block = body_block = self.add_block()
self.current_block = body_block = self.add_block("{}.body".format(name))
self.raise_exn(exn_gen(), loc=loc)
self.current_block = tail_block = self.add_block()
self.current_block = tail_block = self.add_block("{}.tail".format(name))
cond_block.append(ir.BranchIf(cond, tail_block, body_block))
def _make_loop(self, init, cond_gen, body_gen):
def _make_loop(self, init, cond_gen, body_gen, name="loop"):
# init: 'iter Value, initial loop variable value
# cond_gen: lambda('iter Value)->bool Value, loop condition
# body_gen: lambda('iter Value)->'iter Value, loop body,
# returns next loop variable value
init_block = self.current_block
self.current_block = head_block = self.add_block()
self.current_block = head_block = self.add_block("{}.head".format(name))
init_block.append(ir.Branch(head_block))
phi = self.append(ir.Phi(init.type))
phi.add_incoming(init, init_block)
cond = cond_gen(phi)
self.current_block = body_block = self.add_block()
self.current_block = body_block = self.add_block("{}.body".format(name))
body = body_gen(phi)
self.append(ir.Branch(head_block))
phi.add_incoming(body, self.current_block)
self.current_block = tail_block = self.add_block()
self.current_block = tail_block = self.add_block("{}.tail".format(name))
head_block.append(ir.BranchIf(cond, body_block, tail_block))
return head_block, body_block, tail_block
@ -1072,7 +1073,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
prehead = self.current_block
head = self.current_block = self.add_block()
head = self.current_block = self.add_block("slice.head")
prehead.append(ir.Branch(head))
index = self.append(ir.Phi(node.slice.type,
@ -1087,7 +1088,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
bounded_down = self.append(ir.Compare(ast.Gt(loc=None), index, mapped_stop_index))
within_bounds = self.append(ir.Select(counting_up, bounded_up, bounded_down))
body = self.current_block = self.add_block()
body = self.current_block = self.add_block("slice.body")
if self.current_assign is None:
elem = self.iterable_get(value, index)
@ -1103,7 +1104,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
other_index.add_incoming(next_other_index, body)
self.append(ir.Branch(head))
tail = self.current_block = self.add_block()
tail = self.current_block = self.add_block("slice.tail")
head.append(ir.BranchIf(within_bounds, body, tail))
if self.current_assign is None:
@ -1197,7 +1198,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
value_tail = self.current_block
blocks.append((value, value_head, value_tail))
self.current_block = self.add_block()
self.current_block = self.add_block("boolop.seq")
tail = self.current_block
phi = self.append(ir.Phi(node.type))
@ -1366,26 +1367,26 @@ class ARTIQIRGenerator(algorithm.Visitor):
# If the length is the same, compare element-by-element
# and break when the comparison result is false
loop_head = self.add_block()
loop_head = self.add_block("compare.head")
self.current_block = loop_head
index_phi = self.append(ir.Phi(self._size_type))
index_phi.add_incoming(ir.Constant(0, self._size_type), head)
loop_cond = self.append(ir.Compare(ast.Lt(loc=None), index_phi, lhs_length))
loop_body = self.add_block()
loop_body = self.add_block("compare.body")
self.current_block = loop_body
lhs_elt = self.append(ir.GetElem(lhs, index_phi))
rhs_elt = self.append(ir.GetElem(rhs, index_phi))
body_result = self.polymorphic_compare_pair(op, lhs_elt, rhs_elt)
loop_body2 = self.add_block()
loop_body2 = self.add_block("compare.body2")
self.current_block = loop_body2
index_next = self.append(ir.Arith(ast.Add(loc=None), index_phi,
ir.Constant(1, self._size_type)))
self.append(ir.Branch(loop_head))
index_phi.add_incoming(index_next, loop_body2)
tail = self.add_block()
tail = self.add_block("compare.tail")
self.current_block = tail
phi = self.append(ir.Phi(builtins.TBool()))
head.append(ir.BranchIf(eq_length, loop_head, tail))
@ -1431,14 +1432,14 @@ class ARTIQIRGenerator(algorithm.Visitor):
elt = self.iterable_get(haystack, index)
cmp_result = self.polymorphic_compare_pair(ast.Eq(loc=None), needle, elt)
loop_body2 = self.add_block()
loop_body2 = self.add_block("compare.body")
self.current_block = loop_body2
return self.append(ir.Arith(ast.Add(loc=None), index,
ir.Constant(1, length.type)))
loop_head, loop_body, loop_tail = \
self._make_loop(ir.Constant(0, length.type),
lambda index: self.append(ir.Compare(ast.Lt(loc=None), index, length)),
body_gen)
body_gen, name="compare")
loop_body.append(ir.BranchIf(cmp_result, loop_tail, loop_body2))
phi = loop_tail.prepend(ir.Phi(builtins.TBool()))
@ -1479,7 +1480,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
result_tail = self.current_block
blocks.append((result, result_head, result_tail))
self.current_block = self.add_block()
self.current_block = self.add_block("compare.seq")
lhs = rhs
tail = self.current_block
@ -1674,8 +1675,10 @@ class ARTIQIRGenerator(algorithm.Visitor):
fn_typ = callee.type
offset = 0
elif types.is_method(callee.type):
func = self.append(ir.GetAttr(callee, "__func__"))
self_arg = self.append(ir.GetAttr(callee, "__self__"))
func = self.append(ir.GetAttr(callee, "__func__",
name="{}.CLS".format(callee.name)))
self_arg = self.append(ir.GetAttr(callee, "__self__",
name="{}.SLF".format(callee.name)))
fn_typ = types.get_method_function(callee.type)
offset = 1
else:
@ -1719,7 +1722,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
if self.unwind_target is None:
insn = self.append(ir.Call(func, args, arg_exprs))
else:
after_invoke = self.add_block()
after_invoke = self.add_block("invoke")
insn = self.append(ir.Invoke(func, args, arg_exprs,
after_invoke, self.unwind_target))
self.current_block = after_invoke
@ -1734,7 +1737,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
if node.iodelay is not None and not iodelay.is_const(node.iodelay, 0):
before_delay = self.current_block
during_delay = self.add_block()
during_delay = self.add_block("delay.head")
before_delay.append(ir.Branch(during_delay))
self.current_block = during_delay
@ -1748,7 +1751,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
self.method_map[(attr_node.value.type.find(), attr_node.attr)].append(insn)
if node.iodelay is not None and not iodelay.is_const(node.iodelay, 0):
after_delay = self.add_block()
after_delay = self.add_block("delay.tail")
self.append(ir.Delay(node.iodelay, insn, after_delay))
self.current_block = after_delay
@ -1783,7 +1786,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
assert_subexprs = self.current_assert_subexprs = []
init = self.current_block
prehead = self.current_block = self.add_block()
prehead = self.current_block = self.add_block("assert.prehead")
cond = self.visit(node.test)
head = self.current_block
finally:
@ -1795,7 +1798,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
init.append(ir.SetLocal(assert_env, subexpr_name, empty))
init.append(ir.Branch(prehead))
if_failed = self.current_block = self.add_block()
if_failed = self.current_block = self.add_block("assert.fail")
if node.msg:
explanation = node.msg.s
@ -1813,7 +1816,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
subexpr_cond = self.append(ir.Builtin("is_some", [subexpr_value_opt],
builtins.TBool()))
subexpr_body = self.current_block = self.add_block()
subexpr_body = self.current_block = self.add_block("assert.subexpr.body")
self.append(ir.Builtin("printf", [
ir.Constant(" (%s) = ", builtins.TStr()),
ir.Constant(subexpr_node.loc.source(), builtins.TStr())
@ -1823,14 +1826,14 @@ class ARTIQIRGenerator(algorithm.Visitor):
self.polymorphic_print([subexpr_value], separator="", suffix="\n")
subexpr_postbody = self.current_block
subexpr_tail = self.current_block = self.add_block()
subexpr_tail = self.current_block = self.add_block("assert.subexpr.tail")
self.append(ir.Branch(subexpr_tail), block=subexpr_postbody)
self.append(ir.BranchIf(subexpr_cond, subexpr_body, subexpr_tail), block=subexpr_head)
self.append(ir.Builtin("abort", [], builtins.TNone()))
self.append(ir.Unreachable())
tail = self.current_block = self.add_block()
tail = self.current_block = self.add_block("assert.tail")
self.append(ir.BranchIf(cond, tail, if_failed), block=head)
def polymorphic_print(self, values, separator, suffix="", as_repr=False, as_rtio=False):
@ -1904,10 +1907,10 @@ class ARTIQIRGenerator(algorithm.Visitor):
is_last = self.append(ir.Compare(ast.Lt(loc=None), index, last))
head = self.current_block
if_last = self.current_block = self.add_block()
if_last = self.current_block = self.add_block("print.comma")
printf(", ")
tail = self.current_block = self.add_block()
tail = self.current_block = self.add_block("print.tail")
if_last.append(ir.Branch(tail))
head.append(ir.BranchIf(is_last, if_last, tail))

View File

@ -269,11 +269,11 @@ class LLVMIRGenerator:
return llty.as_pointer()
else: # Catch-all for exceptions and custom classes
if builtins.is_exception(typ):
name = "class.Exception" # they all share layout
name = "C.Exception" # they all share layout
elif types.is_constructor(typ):
name = "class.{}".format(typ.name)
name = "C.{}".format(typ.name)
else:
name = "instance.{}".format(typ.name)
name = "I.{}".format(typ.name)
llty = self.llcontext.get_identified_type(name)
if llty.elements is None:
@ -297,7 +297,7 @@ class LLVMIRGenerator:
if name is None:
sanitized_str = re.sub(rb"[^a-zA-Z0-9_.]", b"", as_bytes[:20]).decode('ascii')
name = self.llmodule.get_unique_name("str.{}".format(sanitized_str))
name = self.llmodule.get_unique_name("S.{}".format(sanitized_str))
llstr = self.llmodule.get_global(name)
if llstr is None:
@ -439,16 +439,16 @@ class LLVMIRGenerator:
else:
typ, _ = self.type_map[type(obj_ref)]
llobject = self.llmodule.get_global("object.{}".format(obj_id))
llobject = self.llmodule.get_global("O.{}".format(obj_id))
if llobject is not None:
llobjects[typ].append(llobject.bitcast(llptr))
lldatalayout = llvm.create_target_data(self.llmodule.data_layout)
llrpcattrty = self.llcontext.get_identified_type("attr_desc")
llrpcattrty = self.llcontext.get_identified_type("A")
llrpcattrty.elements = [lli32, lli32, llptr, llptr]
lldescty = self.llcontext.get_identified_type("type_desc")
lldescty = self.llcontext.get_identified_type("D")
lldescty.elements = [llrpcattrty.as_pointer().as_pointer(), llptr.as_pointer()]
lldescs = []
@ -457,9 +457,9 @@ class LLVMIRGenerator:
continue
if types.is_constructor(typ):
type_name = "class.{}".format(typ.name)
type_name = "C.{}".format(typ.name)
else:
type_name = "instance.{}".format(typ.name)
type_name = "I.{}".format(typ.name)
def llrpcattr_of_attr(name, typ):
size = self.llty_of_type(typ). \
@ -478,14 +478,19 @@ class LLVMIRGenerator:
else:
llrpctag = ll.Constant(llptr, None)
llrpcattr = ll.GlobalVariable(self.llmodule, llrpcattrty,
name="attr.{}.{}".format(type_name, name))
llrpcattr.initializer = ll.Constant(llrpcattrty, [
llrpcattrinit = ll.Constant(llrpcattrty, [
ll.Constant(lli32, size),
ll.Constant(lli32, alignment),
llrpctag,
self.llstr_of_str(name)
])
if name == "__objectid__":
return self.get_or_define_global(name, llrpcattrty, llrpcattrinit)
llrpcattr = ll.GlobalVariable(self.llmodule, llrpcattrty,
name="A.{}.{}".format(type_name, name))
llrpcattr.initializer = llrpcattrinit
llrpcattr.global_constant = True
llrpcattr.unnamed_addr = True
llrpcattr.linkage = 'private'
@ -497,7 +502,7 @@ class LLVMIRGenerator:
llrpcattraryty = ll.ArrayType(llrpcattrty.as_pointer(), len(llrpcattrs) + 1)
llrpcattrary = ll.GlobalVariable(self.llmodule, llrpcattraryty,
name="attrs.{}".format(type_name))
name="Ax.{}".format(type_name))
llrpcattrary.initializer = ll.Constant(llrpcattraryty,
llrpcattrs + [ll.Constant(llrpcattrty.as_pointer(), None)])
llrpcattrary.global_constant = True
@ -506,13 +511,13 @@ class LLVMIRGenerator:
llobjectaryty = ll.ArrayType(llptr, len(llobjects[typ]) + 1)
llobjectary = ll.GlobalVariable(self.llmodule, llobjectaryty,
name="objects.{}".format(type_name))
name="Ox.{}".format(type_name))
llobjectary.initializer = ll.Constant(llobjectaryty,
llobjects[typ] + [ll.Constant(llptr, None)])
llobjectary.linkage = 'private'
lldesc = ll.GlobalVariable(self.llmodule, lldescty,
name="desc.{}".format(type_name))
name="D.{}".format(type_name))
lldesc.initializer = ll.Constant(lldescty, [
llrpcattrary.bitcast(llrpcattrty.as_pointer().as_pointer()),
llobjectary.bitcast(llptr.as_pointer())
@ -548,6 +553,7 @@ class LLVMIRGenerator:
llactualargs = self.llfunction.args
for arg, llarg in zip(func.arguments, llactualargs):
llarg.name = arg.name
self.llmap[arg] = llarg
# Second, create all basic blocks.
@ -649,7 +655,8 @@ class LLVMIRGenerator:
def process_GetLocal(self, insn):
env = insn.environment()
llptr = self.llptr_to_var(self.map(env), env.type, insn.var_name)
return self.llbuilder.load(llptr)
llptr.name = "ptr.{}.{}".format(env.name, insn.var_name)
return self.llbuilder.load(llptr, name="val.{}.{}".format(env.name, insn.var_name))
def process_SetLocal(self, insn):
env = insn.environment()
@ -658,6 +665,7 @@ class LLVMIRGenerator:
# We store NoneType as {} but return it as void. So, bail out here.
return ll.Constant(ll.LiteralStructType([]), [])
llptr = self.llptr_to_var(self.map(env), env.type, insn.var_name)
llptr.name = "ptr.{}.{}".format(env.name, insn.var_name)
if isinstance(llvalue, ll.Block):
llvalue = ll.BlockAddress(self.llfunction, llvalue)
if llptr.type.pointee != llvalue.type:
@ -687,13 +695,13 @@ class LLVMIRGenerator:
def get_class(self, typ):
assert types.is_constructor(typ)
llty = self.llty_of_type(typ).pointee
return self.get_or_define_global("class.{}".format(typ.name), llty)
return self.get_or_define_global("C.{}".format(typ.name), llty)
def get_method(self, typ, attr):
assert types.is_constructor(typ)
assert types.is_function(typ.attributes[attr])
llty = self.llty_of_type(typ.attributes[attr])
return self.get_or_define_global("method.{}.{}".format(typ.name, attr), llty)
return self.get_or_define_global("M.{}.{}".format(typ.name, attr), llty)
def process_GetAttr(self, insn):
typ, attr = insn.object().type, insn.attr
@ -715,7 +723,9 @@ class LLVMIRGenerator:
assert False
if types.is_method(insn.type) and attr not in typ.attributes:
llfun = self.llbuilder.load(self.get_method(typ.constructor, attr))
llmethodptr = self.get_method(typ.constructor, attr)
llfun = self.llbuilder.load(llmethodptr)
llfun.name = "met.{}.{}".format(typ.constructor.name, attr)
llself = self.map(insn.object())
llmethodty = self.llty_of_type(insn.type)
@ -727,11 +737,12 @@ class LLVMIRGenerator:
return llmethod
elif types.is_function(insn.type) and attr in typ.attributes and \
types.is_constructor(typ):
return self.llbuilder.load(self.get_method(typ, attr))
llmethodptr = self.get_method(typ, attr)
return self.llbuilder.load(llmethodptr, name="cls.{}".format(llmethodptr.name))
else:
llptr = self.llbuilder.gep(obj, [self.llindex(0), self.llindex(index)],
inbounds=True, name=insn.name)
return self.llbuilder.load(llptr)
inbounds=True, name="ptr.{}".format(insn.name))
return self.llbuilder.load(llptr, name="val.{}".format(insn.name))
def process_SetAttr(self, insn):
typ, attr = insn.object().type, insn.attr
@ -979,8 +990,8 @@ class LLVMIRGenerator:
elif insn.op == "delay_mu":
interval, = insn.operands
llnowptr = self.llbuiltin("now")
llnow = self.llbuilder.load(llnowptr)
lladjusted = self.llbuilder.add(llnow, self.map(interval))
llnow = self.llbuilder.load(llnowptr, name="now.old")
lladjusted = self.llbuilder.add(llnow, self.map(interval), name="now.new")
return self.llbuilder.store(lladjusted, llnowptr)
elif insn.op == "watchdog_set":
interval, = insn.operands
@ -992,11 +1003,12 @@ class LLVMIRGenerator:
assert False
def process_Closure(self, insn):
llenv = self.llbuilder.bitcast(self.map(insn.environment()), llptr)
llenv = self.map(insn.environment())
llenv = self.llbuilder.bitcast(llenv, llptr, name="ptr.{}".format(llenv.name))
if insn.target_function.name in self.function_map.values():
# If this closure belongs to a quoted function, we assume this is the only
# time that the closure is created, and record the environment globally
llenvptr = self.get_or_define_global("env.{}".format(insn.target_function.name),
llenvptr = self.get_or_define_global("E.{}".format(insn.target_function.name),
llptr)
self.llbuilder.store(llenv, llenvptr)
@ -1009,9 +1021,10 @@ class LLVMIRGenerator:
def _prepare_closure_call(self, insn):
llargs = [self.map(arg) for arg in insn.arguments()]
llclosure = self.map(insn.target_function())
llenv = self.llbuilder.extract_value(llclosure, 0)
llenv = self.llbuilder.extract_value(llclosure, 0, name="env.call")
if insn.static_target_function is None:
llfun = self.llbuilder.extract_value(llclosure, 1)
llfun = self.llbuilder.extract_value(llclosure, 1,
name="fun.{}".format(llclosure.name))
else:
llfun = self.map(insn.static_target_function)
return llfun, [llenv] + list(llargs)
@ -1119,15 +1132,18 @@ class LLVMIRGenerator:
lltag = self.llstr_of_str(tag)
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [],
name="rpc.stack")
llargs = []
for arg in args:
for index, arg in enumerate(args):
if builtins.is_none(arg.type):
llargslot = self.llbuilder.alloca(ll.LiteralStructType([]))
llargslot = self.llbuilder.alloca(ll.LiteralStructType([]),
name="rpc.arg{}".format(index))
else:
llarg = self.map(arg)
llargslot = self.llbuilder.alloca(llarg.type)
llargslot = self.llbuilder.alloca(llarg.type,
name="rpc.arg{}".format(index))
self.llbuilder.store(llarg, llargslot)
llargs.append(llargslot)
@ -1144,36 +1160,39 @@ class LLVMIRGenerator:
# else *(T*)ptr
# }
llprehead = self.llbuilder.basic_block
llhead = self.llbuilder.append_basic_block(name=llprehead.name + ".rpc.head")
llhead = self.llbuilder.append_basic_block(name="rpc.head")
if llunwindblock:
llheadu = self.llbuilder.append_basic_block(name=llprehead.name + ".rpc.head.unwind")
llalloc = self.llbuilder.append_basic_block(name=llprehead.name + ".rpc.alloc")
lltail = self.llbuilder.append_basic_block(name=llprehead.name + ".rpc.tail")
llheadu = self.llbuilder.append_basic_block(name="rpc.head.unwind")
llalloc = self.llbuilder.append_basic_block(name="rpc.continue")
lltail = self.llbuilder.append_basic_block(name="rpc.tail")
llretty = self.llty_of_type(fun_type.ret)
llslot = self.llbuilder.alloca(llretty)
llslotgen = self.llbuilder.bitcast(llslot, llptr)
llslot = self.llbuilder.alloca(llretty, name="rpc.ret.alloc")
llslotgen = self.llbuilder.bitcast(llslot, llptr, name="rpc.ret.ptr")
self.llbuilder.branch(llhead)
self.llbuilder.position_at_end(llhead)
llphi = self.llbuilder.phi(llslotgen.type)
llphi = self.llbuilder.phi(llslotgen.type, name="rpc.size")
llphi.add_incoming(llslotgen, llprehead)
if llunwindblock:
llsize = self.llbuilder.invoke(self.llbuiltin("recv_rpc"), [llphi],
llheadu, llunwindblock)
llheadu, llunwindblock,
name="rpc.size.next")
self.llbuilder.position_at_end(llheadu)
else:
llsize = self.llbuilder.call(self.llbuiltin("recv_rpc"), [llphi])
lldone = self.llbuilder.icmp_unsigned('==', llsize, ll.Constant(llsize.type, 0))
llsize = self.llbuilder.call(self.llbuiltin("recv_rpc"), [llphi],
name="rpc.size.next")
lldone = self.llbuilder.icmp_unsigned('==', llsize, ll.Constant(llsize.type, 0),
name="rpc.done")
self.llbuilder.cbranch(lldone, lltail, llalloc)
self.llbuilder.position_at_end(llalloc)
llalloca = self.llbuilder.alloca(lli8, llsize)
llalloca = self.llbuilder.alloca(lli8, llsize, name="rpc.alloc")
llphi.add_incoming(llalloca, llalloc)
self.llbuilder.branch(llhead)
self.llbuilder.position_at_end(lltail)
llret = self.llbuilder.load(llslot)
llret = self.llbuilder.load(llslot, name="rpc.ret")
if not builtins.is_allocated(fun_type.ret):
# We didn't allocate anything except the slot for the value itself.
# Don't waste stack space.
@ -1243,7 +1262,7 @@ class LLVMIRGenerator:
llglobal = self.get_class(typ)
else:
llglobal = ll.GlobalVariable(self.llmodule, llty.pointee,
name="object.{}".format(objectid))
name="O.{}".format(objectid))
self.llobject_map[value_id] = llglobal
else:
@ -1297,7 +1316,7 @@ class LLVMIRGenerator:
def process_Quote(self, insn):
if insn.value in self.function_map:
func_name = self.function_map[insn.value]
llenvptr = self.get_or_define_global("env.{}".format(func_name), llptr)
llenvptr = self.get_or_define_global("E.{}".format(func_name), llptr)
llenv = self.llbuilder.load(llenvptr)
llfun = self.get_function(insn.type.find(), func_name)