mirror of https://github.com/m-labs/artiq.git
compiler: make IR dumps vastly more readable.
This commit is contained in:
parent
eefa9e2ea6
commit
fd46690cf5
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue