From fd46690cf51fde7479131d59aaac68ee73928968 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 17 Nov 2015 00:23:34 +0300 Subject: [PATCH] compiler: make IR dumps vastly more readable. --- artiq/compiler/ir.py | 94 ++++++++++++++++++++++----------------- artiq/compiler/targets.py | 4 +- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/artiq/compiler/ir.py b/artiq/compiler/ir.py index bf487960d..aa428f9b9 100644 --- a/artiq/compiler/ir.py +++ b/artiq/compiler/ir.py @@ -51,6 +51,9 @@ class Value: for user in set(self.uses): user.replace_uses_of(self, value) + def __str__(self): + return self.as_entity(type_printer=types.TypePrinter()) + class Constant(Value): """ A constant value. @@ -62,11 +65,11 @@ class Constant(Value): super().__init__(typ) self.value = value - def as_operand(self): - return str(self) + def as_operand(self, type_printer): + return self.as_entity(type_printer) - def __str__(self): - return "{} {}".format(types.TypePrinter().name(self.type), + def as_entity(self, type_printer): + return "{} {}".format(type_printer.name(self.type), repr(self.value)) class NamedValue(Value): @@ -99,8 +102,8 @@ class NamedValue(Value): def _detach(self): self.function = None - def as_operand(self): - return "{} %{}".format(types.TypePrinter().name(self.type), + def as_operand(self, type_printer): + return "{} %{}".format(type_printer.name(self.type), escape_name(self.name)) class User(NamedValue): @@ -183,18 +186,19 @@ class Instruction(User): else: self.erase() - def _operands_as_string(self): - return ", ".join([operand.as_operand() for operand in self.operands]) + def _operands_as_string(self, type_printer): + return ", ".join([operand.as_operand(type_printer) for operand in self.operands]) - def __str__(self): + def as_entity(self, type_printer): if builtins.is_none(self.type): prefix = "" else: prefix = "%{} = {} ".format(escape_name(self.name), - types.TypePrinter().name(self.type)) + type_printer.name(self.type)) if any(self.operands): - return "{}{} {}".format(prefix, self.opcode(), self._operands_as_string()) + return "{}{} {}".format(prefix, self.opcode(), + self._operands_as_string(type_printer)) else: return "{}{}".format(prefix, self.opcode()) @@ -248,15 +252,16 @@ class Phi(Instruction): self.operands[index].uses.remove(self) del self.operands[index - 1:index + 1] - def __str__(self): + def as_entity(self, type_printer): if builtins.is_none(self.type): prefix = "" else: prefix = "%{} = {} ".format(escape_name(self.name), - types.TypePrinter().name(self.type)) + type_printer.name(self.type)) if any(self.operands): - operand_list = ["%{} => {}".format(escape_name(block.name), value.as_operand()) + operand_list = ["%{} => {}".format(escape_name(block.name), + value.as_operand(type_printer)) for value, block in self.incoming()] return "{}{} [{}]".format(prefix, self.opcode(), ", ".join(operand_list)) else: @@ -346,7 +351,7 @@ class BasicBlock(NamedValue): def predecessors(self): return [use.basic_block for use in self.uses if isinstance(use, Terminator)] - def __str__(self): + def as_entity(self, type_printer): # Header lines = ["{}:".format(escape_name(self.name))] if self.function is not None: @@ -372,7 +377,7 @@ class BasicBlock(NamedValue): 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(" " + insn.as_entity(type_printer)) return "\n".join(lines) @@ -384,8 +389,8 @@ class Argument(NamedValue): A function argument. """ - def __str__(self): - return self.as_operand() + def as_entity(self, type_printer): + return self.as_operand(type_printer) class Function: """ @@ -447,18 +452,20 @@ class Function: for basic_block in self.basic_blocks: yield from iter(basic_block.instructions) - def __str__(self): - printer = types.TypePrinter() + def as_entity(self, type_printer): lines = [] lines.append("{} {}({}) {{ ; type: {}".format( - printer.name(self.type.ret), self.name, - ", ".join([arg.as_operand() for arg in self.arguments]), - printer.name(self.type))) + type_printer.name(self.type.ret), self.name, + ", ".join([arg.as_operand(type_printer) for arg in self.arguments]), + type_printer.name(self.type))) for block in self.basic_blocks: - lines.append(str(block)) + lines.append(block.as_entity(type_printer)) lines.append("}") return "\n".join(lines) + def __str__(self): + return self.as_entity(types.TypePrinter()) + # Python-specific SSA IR classes class TEnvironment(types.TMono): @@ -511,7 +518,7 @@ class EnvironmentArgument(Argument): A function argument specifying an outer environment. """ - def as_operand(self): + def as_operand(self, type_printer): return "environment(...) %{}".format(escape_name(self.name)) class Alloc(Instruction): @@ -527,12 +534,12 @@ class Alloc(Instruction): def opcode(self): return "alloc" - def as_operand(self): + def as_operand(self, type_printer): if is_environment(self.type): # Only show full environment in the instruction itself return "%{}".format(escape_name(self.name)) else: - return super().as_operand() + return super().as_operand(type_printer) class GetLocal(Instruction): """ @@ -875,8 +882,8 @@ class Call(Instruction): def arguments(self): return self.operands[1:] - def __str__(self): - result = super().__str__() + def as_entity(self, type_printer): + result = super().as_entity(type_printer) if self.static_target_function is not None: result += " ; calls {}".format(self.static_target_function.name) return result @@ -1003,9 +1010,10 @@ class IndirectBranch(Terminator): destination.uses.add(self) self.operands.append(destination) - def _operands_as_string(self): - return "{}, [{}]".format(self.operands[0].as_operand(), - ", ".join([dest.as_operand() for dest in self.operands[1:]])) + def _operands_as_string(self, type_printer): + return "{}, [{}]".format(self.operands[0].as_operand(type_printer), + ", ".join([dest.as_operand(type_printer) + for dest in self.operands[1:]])) class Return(Terminator): """ @@ -1125,14 +1133,14 @@ class Invoke(Terminator): def exception_target(self): return self.operands[-1] - def _operands_as_string(self): - result = ", ".join([operand.as_operand() for operand in self.operands[:-2]]) - result += " to {} unwind {}".format(self.operands[-2].as_operand(), - self.operands[-1].as_operand()) + def _operands_as_string(self, type_printer): + result = ", ".join([operand.as_operand(type_printer) for operand in self.operands[:-2]]) + result += " to {} unwind {}".format(self.operands[-2].as_operand(type_printer), + self.operands[-1].as_operand(type_printer)) return result - def __str__(self): - result = super().__str__() + def as_entity(self, type_printer): + result = super().as_entity(type_printer) if self.static_target_function is not None: result += " ; calls {}".format(self.static_target_function.name) return result @@ -1169,14 +1177,16 @@ class LandingPad(Terminator): self.types.append(typ.find() if typ is not None else None) target.uses.add(self) - def _operands_as_string(self): + def _operands_as_string(self, type_printer): table = [] for target, typ in self.clauses(): if typ is None: - table.append("... => {}".format(target.as_operand())) + table.append("... => {}".format(target.as_operand(type_printer))) else: - table.append("{} => {}".format(types.TypePrinter().name(typ), target.as_operand())) - return "cleanup {}, [{}]".format(self.cleanup().as_operand(), ", ".join(table)) + table.append("{} => {}".format(type_printer.name(typ), + target.as_operand(type_printer))) + return "cleanup {}, [{}]".format(self.cleanup().as_operand(type_printer), + ", ".join(table)) class Parallel(Terminator): """ diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index 2194b73b5..8889ee67c 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -1,4 +1,5 @@ import os, sys, tempfile, subprocess +from artiq.compiler import types from llvmlite_artiq import ir as ll, binding as llvm llvm.initialize() @@ -75,8 +76,9 @@ class Target: if os.getenv("ARTIQ_DUMP_IR"): print("====== ARTIQ IR DUMP ======", file=sys.stderr) + type_printer = types.TypePrinter() for function in module.artiq_ir: - print(function, file=sys.stderr) + print(function.as_entity(type_printer), file=sys.stderr) llmod = module.build_llvm_ir(self) llparsedmod = llvm.parse_assembly(str(llmod))