mirror of https://github.com/m-labs/artiq.git
Add source locations to ARTIQ IR instructions.
This commit is contained in:
parent
255ffec483
commit
dde2e67c3f
|
@ -133,6 +133,7 @@ class Instruction(User):
|
||||||
assert isinstance(typ, types.Type)
|
assert isinstance(typ, types.Type)
|
||||||
super().__init__(operands, typ, name)
|
super().__init__(operands, typ, name)
|
||||||
self.basic_block = None
|
self.basic_block = None
|
||||||
|
self.loc = None
|
||||||
|
|
||||||
def set_basic_block(self, new_basic_block):
|
def set_basic_block(self, new_basic_block):
|
||||||
self.basic_block = new_basic_block
|
self.basic_block = new_basic_block
|
||||||
|
@ -306,12 +307,33 @@ class BasicBlock(NamedValue):
|
||||||
return self.function.predecessors_of(self)
|
return self.function.predecessors_of(self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
# Header
|
||||||
lines = ["{}:".format(escape_name(self.name))]
|
lines = ["{}:".format(escape_name(self.name))]
|
||||||
if self.function is not None:
|
if self.function is not None:
|
||||||
lines[0] += " ; predecessors: {}".format(
|
lines[0] += " ; predecessors: {}".format(
|
||||||
", ".join([escape_name(pred.name) for pred in self.predecessors()]))
|
", ".join([escape_name(pred.name) for pred in self.predecessors()]))
|
||||||
|
|
||||||
|
# Annotated instructions
|
||||||
|
loc = None
|
||||||
for insn in self.instructions:
|
for insn in self.instructions:
|
||||||
|
if loc != insn.loc:
|
||||||
|
loc = insn.loc
|
||||||
|
|
||||||
|
if loc is None:
|
||||||
|
lines.append("; <synthesized>")
|
||||||
|
else:
|
||||||
|
source_lines = loc.source_lines()
|
||||||
|
beg_col, end_col = loc.column(), loc.end().column()
|
||||||
|
source_lines[-1] = \
|
||||||
|
source_lines[-1][:end_col] + "`" + source_lines[-1][end_col:]
|
||||||
|
source_lines[0] = \
|
||||||
|
source_lines[0][:beg_col] + "`" + source_lines[0][beg_col:]
|
||||||
|
|
||||||
|
line_desc = "{}:{}".format(loc.source_buffer.name, loc.line())
|
||||||
|
lines += ["; {} {}".format(line_desc, line.rstrip("\n"))
|
||||||
|
for line in source_lines]
|
||||||
lines.append(" " + str(insn))
|
lines.append(" " + str(insn))
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
class Argument(NamedValue):
|
class Argument(NamedValue):
|
||||||
|
|
|
@ -16,6 +16,12 @@ def _readable_name(insn):
|
||||||
else:
|
else:
|
||||||
return insn.name
|
return insn.name
|
||||||
|
|
||||||
|
def _extract_loc(node):
|
||||||
|
if "keyword_loc" in node._locs:
|
||||||
|
return node.keyword_loc
|
||||||
|
else:
|
||||||
|
return node.loc
|
||||||
|
|
||||||
# We put some effort in keeping generated IR readable,
|
# We put some effort in keeping generated IR readable,
|
||||||
# i.e. with a more or less linear correspondence to the source.
|
# i.e. with a more or less linear correspondence to the source.
|
||||||
# This is why basic blocks sometimes seem to be produced in an odd order.
|
# This is why basic blocks sometimes seem to be produced in an odd order.
|
||||||
|
@ -25,8 +31,10 @@ class IRGenerator(algorithm.Visitor):
|
||||||
which is effectively maintained in a stack--with push/pop
|
which is effectively maintained in a stack--with push/pop
|
||||||
pairs around any state updates. It is comprised of following:
|
pairs around any state updates. It is comprised of following:
|
||||||
|
|
||||||
|
:ivar current_loc: (:class:`pythonparser.source.Range`)
|
||||||
|
source range of the node being currently visited
|
||||||
:ivar current_function: (:class:`ir.Function` or None)
|
:ivar current_function: (:class:`ir.Function` or None)
|
||||||
def or lambda currently being translated
|
module, def or lambda currently being translated
|
||||||
:ivar current_block: (:class:`ir.BasicBlock`)
|
:ivar current_block: (:class:`ir.BasicBlock`)
|
||||||
basic block to which any new instruction will be appended
|
basic block to which any new instruction will be appended
|
||||||
:ivar current_env: (:class:`ir.Environment`)
|
:ivar current_env: (:class:`ir.Environment`)
|
||||||
|
@ -55,6 +63,7 @@ class IRGenerator(algorithm.Visitor):
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
self.functions = []
|
self.functions = []
|
||||||
self.name = [module_name]
|
self.name = [module_name]
|
||||||
|
self.current_loc = None
|
||||||
self.current_function = None
|
self.current_function = None
|
||||||
self.current_block = None
|
self.current_block = None
|
||||||
self.current_env = None
|
self.current_env = None
|
||||||
|
@ -70,8 +79,15 @@ class IRGenerator(algorithm.Visitor):
|
||||||
self.current_function.add(block)
|
self.current_function.add(block)
|
||||||
return block
|
return block
|
||||||
|
|
||||||
def append(self, insn):
|
def append(self, insn, block=None, loc=None):
|
||||||
return self.current_block.append(insn)
|
if loc is None:
|
||||||
|
loc = self.current_loc
|
||||||
|
if block is None:
|
||||||
|
block = self.current_block
|
||||||
|
|
||||||
|
if insn.loc is None:
|
||||||
|
insn.loc = self.current_loc
|
||||||
|
return block.append(insn)
|
||||||
|
|
||||||
def terminate(self, insn):
|
def terminate(self, insn):
|
||||||
if not self.current_block.is_terminated():
|
if not self.current_block.is_terminated():
|
||||||
|
@ -88,11 +104,18 @@ class IRGenerator(algorithm.Visitor):
|
||||||
if self.current_block.is_terminated():
|
if self.current_block.is_terminated():
|
||||||
break
|
break
|
||||||
elif isinstance(obj, ast.AST):
|
elif isinstance(obj, ast.AST):
|
||||||
|
try:
|
||||||
|
old_loc, self.current_loc = self.current_loc, _extract_loc(obj)
|
||||||
return self._visit_one(obj)
|
return self._visit_one(obj)
|
||||||
|
finally:
|
||||||
|
self.current_loc = old_loc
|
||||||
|
|
||||||
# Module visitor
|
# Module visitor
|
||||||
|
|
||||||
def visit_ModuleT(self, node):
|
def visit_ModuleT(self, node):
|
||||||
|
# Treat start of module as synthesized
|
||||||
|
self.current_loc = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
typ = types.TFunction(OrderedDict(), OrderedDict(), builtins.TNone())
|
typ = types.TFunction(OrderedDict(), OrderedDict(), builtins.TNone())
|
||||||
func = ir.Function(typ, ".".join(self.name + ['__modinit__']), [])
|
func = ir.Function(typ, ".".join(self.name + ['__modinit__']), [])
|
||||||
|
|
Loading…
Reference in New Issue