From dde2e67c3f46d7442216c31ca267f46b296784e9 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 18 Jul 2015 07:49:42 +0300 Subject: [PATCH] Add source locations to ARTIQ IR instructions. --- artiq/compiler/ir.py | 22 ++++++++++++++++ artiq/compiler/transforms/ir_generator.py | 31 ++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/artiq/compiler/ir.py b/artiq/compiler/ir.py index 9e04c0231..b7977cc10 100644 --- a/artiq/compiler/ir.py +++ b/artiq/compiler/ir.py @@ -133,6 +133,7 @@ class Instruction(User): assert isinstance(typ, types.Type) super().__init__(operands, typ, name) self.basic_block = None + self.loc = None def set_basic_block(self, new_basic_block): self.basic_block = new_basic_block @@ -306,12 +307,33 @@ class BasicBlock(NamedValue): return self.function.predecessors_of(self) def __str__(self): + # Header lines = ["{}:".format(escape_name(self.name))] if self.function is not None: lines[0] += " ; predecessors: {}".format( ", ".join([escape_name(pred.name) for pred in self.predecessors()])) + + # Annotated instructions + loc = None for insn in self.instructions: + if loc != insn.loc: + loc = insn.loc + + if loc is None: + lines.append("; ") + 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)) + return "\n".join(lines) class Argument(NamedValue): diff --git a/artiq/compiler/transforms/ir_generator.py b/artiq/compiler/transforms/ir_generator.py index ef0214695..17372cd17 100644 --- a/artiq/compiler/transforms/ir_generator.py +++ b/artiq/compiler/transforms/ir_generator.py @@ -16,6 +16,12 @@ def _readable_name(insn): else: 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, # 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. @@ -25,8 +31,10 @@ class IRGenerator(algorithm.Visitor): which is effectively maintained in a stack--with push/pop 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) - def or lambda currently being translated + module, def or lambda currently being translated :ivar current_block: (:class:`ir.BasicBlock`) basic block to which any new instruction will be appended :ivar current_env: (:class:`ir.Environment`) @@ -55,6 +63,7 @@ class IRGenerator(algorithm.Visitor): self.engine = engine self.functions = [] self.name = [module_name] + self.current_loc = None self.current_function = None self.current_block = None self.current_env = None @@ -70,8 +79,15 @@ class IRGenerator(algorithm.Visitor): self.current_function.add(block) return block - def append(self, insn): - return self.current_block.append(insn) + def append(self, insn, block=None, loc=None): + 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): if not self.current_block.is_terminated(): @@ -88,11 +104,18 @@ class IRGenerator(algorithm.Visitor): if self.current_block.is_terminated(): break elif isinstance(obj, ast.AST): - return self._visit_one(obj) + try: + old_loc, self.current_loc = self.current_loc, _extract_loc(obj) + return self._visit_one(obj) + finally: + self.current_loc = old_loc # Module visitor def visit_ModuleT(self, node): + # Treat start of module as synthesized + self.current_loc = None + try: typ = types.TFunction(OrderedDict(), OrderedDict(), builtins.TNone()) func = ir.Function(typ, ".".join(self.name + ['__modinit__']), [])