forked from M-Labs/artiq
1
0
Fork 0

compiler: make IR dumps vastly more readable.

This commit is contained in:
whitequark 2015-11-17 00:23:34 +03:00
parent eefa9e2ea6
commit fd46690cf5
2 changed files with 55 additions and 43 deletions

View File

@ -51,6 +51,9 @@ class Value:
for user in set(self.uses): for user in set(self.uses):
user.replace_uses_of(self, value) user.replace_uses_of(self, value)
def __str__(self):
return self.as_entity(type_printer=types.TypePrinter())
class Constant(Value): class Constant(Value):
""" """
A constant value. A constant value.
@ -62,11 +65,11 @@ class Constant(Value):
super().__init__(typ) super().__init__(typ)
self.value = value self.value = value
def as_operand(self): def as_operand(self, type_printer):
return str(self) return self.as_entity(type_printer)
def __str__(self): def as_entity(self, type_printer):
return "{} {}".format(types.TypePrinter().name(self.type), return "{} {}".format(type_printer.name(self.type),
repr(self.value)) repr(self.value))
class NamedValue(Value): class NamedValue(Value):
@ -99,8 +102,8 @@ class NamedValue(Value):
def _detach(self): def _detach(self):
self.function = None self.function = None
def as_operand(self): def as_operand(self, type_printer):
return "{} %{}".format(types.TypePrinter().name(self.type), return "{} %{}".format(type_printer.name(self.type),
escape_name(self.name)) escape_name(self.name))
class User(NamedValue): class User(NamedValue):
@ -183,18 +186,19 @@ class Instruction(User):
else: else:
self.erase() self.erase()
def _operands_as_string(self): def _operands_as_string(self, type_printer):
return ", ".join([operand.as_operand() for operand in self.operands]) 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): if builtins.is_none(self.type):
prefix = "" prefix = ""
else: else:
prefix = "%{} = {} ".format(escape_name(self.name), prefix = "%{} = {} ".format(escape_name(self.name),
types.TypePrinter().name(self.type)) type_printer.name(self.type))
if any(self.operands): 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: else:
return "{}{}".format(prefix, self.opcode()) return "{}{}".format(prefix, self.opcode())
@ -248,15 +252,16 @@ class Phi(Instruction):
self.operands[index].uses.remove(self) self.operands[index].uses.remove(self)
del self.operands[index - 1:index + 1] del self.operands[index - 1:index + 1]
def __str__(self): def as_entity(self, type_printer):
if builtins.is_none(self.type): if builtins.is_none(self.type):
prefix = "" prefix = ""
else: else:
prefix = "%{} = {} ".format(escape_name(self.name), prefix = "%{} = {} ".format(escape_name(self.name),
types.TypePrinter().name(self.type)) type_printer.name(self.type))
if any(self.operands): 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()] for value, block in self.incoming()]
return "{}{} [{}]".format(prefix, self.opcode(), ", ".join(operand_list)) return "{}{} [{}]".format(prefix, self.opcode(), ", ".join(operand_list))
else: else:
@ -346,7 +351,7 @@ class BasicBlock(NamedValue):
def predecessors(self): def predecessors(self):
return [use.basic_block for use in self.uses if isinstance(use, Terminator)] return [use.basic_block for use in self.uses if isinstance(use, Terminator)]
def __str__(self): def as_entity(self, type_printer):
# Header # 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:
@ -372,7 +377,7 @@ class BasicBlock(NamedValue):
line_desc = "{}:{}".format(loc.source_buffer.name, loc.line()) line_desc = "{}:{}".format(loc.source_buffer.name, loc.line())
lines += ["; {} {}".format(line_desc, line.rstrip("\n")) lines += ["; {} {}".format(line_desc, line.rstrip("\n"))
for line in source_lines] for line in source_lines]
lines.append(" " + str(insn)) lines.append(" " + insn.as_entity(type_printer))
return "\n".join(lines) return "\n".join(lines)
@ -384,8 +389,8 @@ class Argument(NamedValue):
A function argument. A function argument.
""" """
def __str__(self): def as_entity(self, type_printer):
return self.as_operand() return self.as_operand(type_printer)
class Function: class Function:
""" """
@ -447,18 +452,20 @@ class Function:
for basic_block in self.basic_blocks: for basic_block in self.basic_blocks:
yield from iter(basic_block.instructions) yield from iter(basic_block.instructions)
def __str__(self): def as_entity(self, type_printer):
printer = types.TypePrinter()
lines = [] lines = []
lines.append("{} {}({}) {{ ; type: {}".format( lines.append("{} {}({}) {{ ; type: {}".format(
printer.name(self.type.ret), self.name, type_printer.name(self.type.ret), self.name,
", ".join([arg.as_operand() for arg in self.arguments]), ", ".join([arg.as_operand(type_printer) for arg in self.arguments]),
printer.name(self.type))) type_printer.name(self.type)))
for block in self.basic_blocks: for block in self.basic_blocks:
lines.append(str(block)) lines.append(block.as_entity(type_printer))
lines.append("}") lines.append("}")
return "\n".join(lines) return "\n".join(lines)
def __str__(self):
return self.as_entity(types.TypePrinter())
# Python-specific SSA IR classes # Python-specific SSA IR classes
class TEnvironment(types.TMono): class TEnvironment(types.TMono):
@ -511,7 +518,7 @@ class EnvironmentArgument(Argument):
A function argument specifying an outer environment. A function argument specifying an outer environment.
""" """
def as_operand(self): def as_operand(self, type_printer):
return "environment(...) %{}".format(escape_name(self.name)) return "environment(...) %{}".format(escape_name(self.name))
class Alloc(Instruction): class Alloc(Instruction):
@ -527,12 +534,12 @@ class Alloc(Instruction):
def opcode(self): def opcode(self):
return "alloc" return "alloc"
def as_operand(self): def as_operand(self, type_printer):
if is_environment(self.type): if is_environment(self.type):
# Only show full environment in the instruction itself # Only show full environment in the instruction itself
return "%{}".format(escape_name(self.name)) return "%{}".format(escape_name(self.name))
else: else:
return super().as_operand() return super().as_operand(type_printer)
class GetLocal(Instruction): class GetLocal(Instruction):
""" """
@ -875,8 +882,8 @@ class Call(Instruction):
def arguments(self): def arguments(self):
return self.operands[1:] return self.operands[1:]
def __str__(self): def as_entity(self, type_printer):
result = super().__str__() result = super().as_entity(type_printer)
if self.static_target_function is not None: if self.static_target_function is not None:
result += " ; calls {}".format(self.static_target_function.name) result += " ; calls {}".format(self.static_target_function.name)
return result return result
@ -1003,9 +1010,10 @@ class IndirectBranch(Terminator):
destination.uses.add(self) destination.uses.add(self)
self.operands.append(destination) self.operands.append(destination)
def _operands_as_string(self): def _operands_as_string(self, type_printer):
return "{}, [{}]".format(self.operands[0].as_operand(), return "{}, [{}]".format(self.operands[0].as_operand(type_printer),
", ".join([dest.as_operand() for dest in self.operands[1:]])) ", ".join([dest.as_operand(type_printer)
for dest in self.operands[1:]]))
class Return(Terminator): class Return(Terminator):
""" """
@ -1125,14 +1133,14 @@ class Invoke(Terminator):
def exception_target(self): def exception_target(self):
return self.operands[-1] return self.operands[-1]
def _operands_as_string(self): def _operands_as_string(self, type_printer):
result = ", ".join([operand.as_operand() for operand in self.operands[:-2]]) result = ", ".join([operand.as_operand(type_printer) for operand in self.operands[:-2]])
result += " to {} unwind {}".format(self.operands[-2].as_operand(), result += " to {} unwind {}".format(self.operands[-2].as_operand(type_printer),
self.operands[-1].as_operand()) self.operands[-1].as_operand(type_printer))
return result return result
def __str__(self): def as_entity(self, type_printer):
result = super().__str__() result = super().as_entity(type_printer)
if self.static_target_function is not None: if self.static_target_function is not None:
result += " ; calls {}".format(self.static_target_function.name) result += " ; calls {}".format(self.static_target_function.name)
return result return result
@ -1169,14 +1177,16 @@ class LandingPad(Terminator):
self.types.append(typ.find() if typ is not None else None) self.types.append(typ.find() if typ is not None else None)
target.uses.add(self) target.uses.add(self)
def _operands_as_string(self): def _operands_as_string(self, type_printer):
table = [] table = []
for target, typ in self.clauses(): for target, typ in self.clauses():
if typ is None: if typ is None:
table.append("... => {}".format(target.as_operand())) table.append("... => {}".format(target.as_operand(type_printer)))
else: else:
table.append("{} => {}".format(types.TypePrinter().name(typ), target.as_operand())) table.append("{} => {}".format(type_printer.name(typ),
return "cleanup {}, [{}]".format(self.cleanup().as_operand(), ", ".join(table)) target.as_operand(type_printer)))
return "cleanup {}, [{}]".format(self.cleanup().as_operand(type_printer),
", ".join(table))
class Parallel(Terminator): class Parallel(Terminator):
""" """

View File

@ -1,4 +1,5 @@
import os, sys, tempfile, subprocess import os, sys, tempfile, subprocess
from artiq.compiler import types
from llvmlite_artiq import ir as ll, binding as llvm from llvmlite_artiq import ir as ll, binding as llvm
llvm.initialize() llvm.initialize()
@ -75,8 +76,9 @@ class Target:
if os.getenv("ARTIQ_DUMP_IR"): if os.getenv("ARTIQ_DUMP_IR"):
print("====== ARTIQ IR DUMP ======", file=sys.stderr) print("====== ARTIQ IR DUMP ======", file=sys.stderr)
type_printer = types.TypePrinter()
for function in module.artiq_ir: 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) llmod = module.build_llvm_ir(self)
llparsedmod = llvm.parse_assembly(str(llmod)) llparsedmod = llvm.parse_assembly(str(llmod))