Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7e3f91c0bba8
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6f11fa6bb1a9
Choose a head ref
  • 2 commits
  • 8 files changed
  • 1 contributor

Commits on Jul 19, 2015

  1. Fix artiq.compiler.ir.BasicBlock.__repr__.

    whitequark committed Jul 19, 2015
    Copy the full SHA
    c6cd318 View commit details

Commits on Jul 21, 2015

  1. Copy the full SHA
    6f11fa6 View commit details
12 changes: 9 additions & 3 deletions artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -19,10 +19,16 @@ class TBasicBlock(types.TMono):
def __init__(self):
super().__init__("label")

def is_basic_block(typ):
return isinstance(typ, TBasicBlock)

class TOption(types.TMono):
def __init__(self, inner):
super().__init__("option", {"inner": inner})

def is_option(typ):
return isinstance(typ, TOption)

class Value:
"""
An SSA value that keeps track of its uses.
@@ -341,7 +347,7 @@ def __str__(self):
return "\n".join(lines)

def __repr__(self):
return "<BasicBlock '{}'>".format(self.name)
return "<artiq.compiler.ir.BasicBlock {}>".format(repr(self.name))

class Argument(NamedValue):
"""
@@ -571,7 +577,7 @@ def __init__(self, obj, attr, name=""):
def opcode(self):
return "getattr({})".format(repr(self.attr))

def env(self):
def object(self):
return self.operands[0]

class SetAttr(Instruction):
@@ -600,7 +606,7 @@ def __init__(self, obj, attr, value, name=""):
def opcode(self):
return "setattr({})".format(repr(self.attr))

def env(self):
def object(self):
return self.operands[0]

def value(self):
11 changes: 7 additions & 4 deletions artiq/compiler/module.py
Original file line number Diff line number Diff line change
@@ -18,9 +18,10 @@ def __init__(self, source_buffer, engine=None):
int_monomorphizer = transforms.IntMonomorphizer(engine=engine)
monomorphism_validator = validators.MonomorphismValidator(engine=engine)
escape_validator = validators.EscapeValidator(engine=engine)
ir_generator = transforms.IRGenerator(engine=engine, module_name=self.name)
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=engine, module_name=self.name)
dead_code_eliminator = transforms.DeadCodeEliminator(engine=engine)
local_access_validator = validators.LocalAccessValidator(engine=engine)
llvm_ir_generator = transforms.LLVMIRGenerator(engine=engine, module_name=self.name)

self.parsetree, self.comments = parse_buffer(source_buffer, engine=engine)
self.typedtree = asttyped_rewriter.visit(self.parsetree)
@@ -30,9 +31,11 @@ def __init__(self, source_buffer, engine=None):
inferencer.visit(self.typedtree)
monomorphism_validator.visit(self.typedtree)
escape_validator.visit(self.typedtree)
self.ir = ir_generator.visit(self.typedtree)
dead_code_eliminator.process(self.ir)
local_access_validator.process(self.ir)
self.artiq_ir = artiq_ir_generator.visit(self.typedtree)
dead_code_eliminator.process(self.artiq_ir)
local_access_validator.process(self.artiq_ir)
llvm_ir_generator.process(self.artiq_ir)
self.llvm_ir = llvm_ir_generator.llmodule

@classmethod
def from_string(cls, source_string, name="input.py", first_line=1, engine=None):
2 changes: 1 addition & 1 deletion artiq/compiler/testbench/irgen.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ def process_diagnostic(diag):
engine.process = process_diagnostic

mod = Module.from_string("".join(fileinput.input()).expandtabs(), engine=engine)
for fn in mod.ir:
for fn in mod.artiq_ir:
print(fn)

if __name__ == "__main__":
18 changes: 18 additions & 0 deletions artiq/compiler/testbench/llvmgen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sys, fileinput
from pythonparser import diagnostic
from .. import Module

def main():
def process_diagnostic(diag):
print("\n".join(diag.render()))
if diag.level in ("fatal", "error"):
exit(1)

engine = diagnostic.Engine()
engine.process = process_diagnostic

mod = Module.from_string("".join(fileinput.input()).expandtabs(), engine=engine)
print(mod.llvm_ir)

if __name__ == "__main__":
main()
3 changes: 2 additions & 1 deletion artiq/compiler/transforms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .asttyped_rewriter import ASTTypedRewriter
from .inferencer import Inferencer
from .int_monomorphizer import IntMonomorphizer
from .ir_generator import IRGenerator
from .artiq_ir_generator import ARTIQIRGenerator
from .dead_code_eliminator import DeadCodeEliminator
from .llvm_ir_generator import LLVMIRGenerator
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
:class:`IRGenerator` transforms typed AST into ARTIQ intermediate
:class:`ARTIQIRGenerator` transforms typed AST into ARTIQ intermediate
representation. ARTIQ IR is designed to be low-level enough that
its operations are elementary--contain no internal branching--
but without too much detail, such as exposing the reference/value
@@ -25,9 +25,9 @@ def _extract_loc(node):
# 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.
class IRGenerator(algorithm.Visitor):
class ARTIQIRGenerator(algorithm.Visitor):
"""
:class:`IRGenerator` contains a lot of internal state,
:class:`ARTIQIRGenerator` contains a lot of internal state,
which is effectively maintained in a stack--with push/pop
pairs around any state updates. It is comprised of following:
@@ -255,8 +255,7 @@ def visit_Expr(self, node):
def visit_Pass(self, node):
# Insert a dummy instruction so that analyses which extract
# locations from CFG have something to use.
self.append(ir.Arith(ast.Add(loc=None),
ir.Constant(0, self._size_type), ir.Constant(0, self._size_type)))
self.append(ir.Builtin("nop", [], builtins.TNone()))

def visit_Assign(self, node):
try:
@@ -367,12 +366,13 @@ def visit_For(self, node):
try:
iterable = self.visit(node.iter)
length = self._iterable_len(iterable)
prehead = self.current_block

head = self.add_block("for.head")
self.append(ir.Branch(head))
self.current_block = head
phi = self.append(ir.Phi(length.type))
phi.add_incoming(ir.Constant(0, phi.type), head)
phi.add_incoming(ir.Constant(0, phi.type), prehead)
cond = self.append(ir.Compare(ast.Lt(loc=None), phi, length))

break_block = self.add_block("for.break")
@@ -842,6 +842,8 @@ def visit_CoerceT(self, node):

def visit_BinOpT(self, node):
if builtins.is_numeric(node.type):
# TODO: check for division by zero
# TODO: check for shift by too many bits
return self.append(ir.Arith(node.op, self.visit(node.left), self.visit(node.right)))
elif isinstance(node.op, ast.Add): # list + list, tuple + tuple
lhs, rhs = self.visit(node.left), self.visit(node.right)
5 changes: 4 additions & 1 deletion artiq/compiler/transforms/inferencer.py
Original file line number Diff line number Diff line change
@@ -335,9 +335,12 @@ def _coerce_binop(self, op, left, right):
return list_.type, left.type, right.type
else:
return self._coerce_numeric((left, right), lambda typ: (typ, typ, typ))
elif isinstance(op, (ast.Div, ast.FloorDiv, ast.Mod, ast.Pow, ast.Sub)):
elif isinstance(op, (ast.FloorDiv, ast.Mod, ast.Pow, ast.Sub)):
# numeric operators work on any kind of number
return self._coerce_numeric((left, right), lambda typ: (typ, typ, typ))
elif isinstance(op, ast.Div):
# division always returns a float
return self._coerce_numeric((left, right), lambda typ: (builtins.TFloat(), typ, typ))
else: # MatMult
diag = diagnostic.Diagnostic("error",
"operator '{op}' is not supported", {"op": op.loc.source()},
Loading