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: 86ba219c1103
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: ce30045dd4b8
Choose a head ref
  • 6 commits
  • 6 files changed
  • 1 contributor

Commits on Apr 2, 2016

  1. coredevice: format backtrace RA as +0xN, not 0xN.

    The absolute address is somewhere in the 0x4000000 range; the one
    that is displayed is an offset from the shared object base.
    whitequark committed Apr 2, 2016
    Copy the full SHA
    132b55d View commit details
  2. Copy the full SHA
    b1f371e View commit details
  3. llvm_ir_generator: add TBAA metadata for @now.

    whitequark committed Apr 2, 2016
    Copy the full SHA
    a1e98a4 View commit details
  4. Copy the full SHA
    712e16b View commit details
  5. compiler: purge generated functions from backtraces.

    whitequark committed Apr 2, 2016
    Copy the full SHA
    a57aabb View commit details
  6. conda: update llvmlite-artiq dependency.

    Build 22 includes debug information support.
    whitequark committed Apr 2, 2016
    Copy the full SHA
    ce30045 View commit details
3 changes: 3 additions & 0 deletions artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -425,6 +425,8 @@ class Function:
the module it is contained in
:ivar is_cold:
(bool) if True, the function should be considered rarely called
:ivar is_generated:
(bool) if True, the function will not appear in backtraces
:ivar flags: (set of str) Code generation flags.
Flag ``fast-math`` is the equivalent of gcc's ``-ffast-math``.
"""
@@ -436,6 +438,7 @@ def __init__(self, typ, name, arguments, loc=None):
self.set_arguments(arguments)
self.is_internal = False
self.is_cold = False
self.is_generated = False
self.flags = {}

def _remove_name(self, name):
1 change: 1 addition & 0 deletions artiq/compiler/transforms/artiq_ir_generator.py
Original file line number Diff line number Diff line change
@@ -944,6 +944,7 @@ def _make_check(self, cond, exn_gen, loc=None, params=[]):
func = ir.Function(typ, ".".join(self.name + [name]), args, loc=loc)
func.is_internal = True
func.is_cold = True
func.is_generated = True
self.functions.append(func)
old_func, self.current_function = self.current_function, func

170 changes: 72 additions & 98 deletions artiq/compiler/transforms/llvm_ir_generator.py
Original file line number Diff line number Diff line change
@@ -42,126 +42,89 @@ def memoized(self, *args):
class DebugInfoEmitter:
def __init__(self, llmodule):
self.llmodule = llmodule
self.llsubprograms = []
self.cache = {}
self.subprograms = []

def emit(self, operands):
def emit_metadata(self, operands):
def map_operand(operand):
if operand is None:
return ll.Constant(llmetadata, None)
elif isinstance(operand, str):
return ll.MetaDataString(self.llmodule, operand)
elif isinstance(operand, bool):
return ll.Constant(lli1, operand)
elif isinstance(operand, int):
return ll.Constant(lli32, operand)
elif isinstance(operand, (list, tuple)):
return self.emit(operand)
elif isinstance(operand, ll.Value):
return operand
return self.emit_metadata(operand)
else:
print(operand)
assert False
assert isinstance(operand, ll.NamedValue)
return operand
return self.llmodule.add_metadata(list(map(map_operand, operands)))

def emit_debug_info(self, kind, operands, is_distinct=False):
return self.llmodule.add_debug_info(kind, operands, is_distinct)

@memoize
def emit_filename(self, source_buffer):
def emit_file(self, source_buffer):
source_dir, source_file = os.path.split(source_buffer.name)
return self.emit([source_file, source_dir])
return self.emit_debug_info("DIFile", {
"filename": source_file,
"directory": source_dir,
})

@memoize
def emit_compile_unit(self, source_buffer, llsubprograms):
return self.emit([
DW_TAG_compile_unit,
self.emit_filename(source_buffer), # filename
DW_LANG_Python, # source language
"ARTIQ", # producer
False, # optimized?
"", # linker flags
0, # runtime version
[], # enum types
[], # retained types
llsubprograms, # subprograms
[], # global variables
[], # imported entities
"", # split debug filename
2, # kind (full=1, lines only=2)
])

@memoize
def emit_file(self, source_buffer):
return self.emit([
DW_TAG_file_type,
self.emit_filename(source_buffer), # filename
])
return self.emit_debug_info("DICompileUnit", {
"language": ll.DIToken("DW_LANG_C99"),
"file": self.emit_file(source_buffer),
"producer": "ARTIQ",
"runtimeVersion": 0,
"emissionKind": 2, # full=1, lines only=2
"subprograms": self.emit_metadata(llsubprograms)
}, is_distinct=True)

@memoize
def emit_subroutine_type(self, typ):
return self.emit([
DW_TAG_subroutine_type,
None, # filename
None, # context descriptor
"", # name
0, # line number
0, # (i64) size in bits
0, # (i64) alignment in bits
0, # (i64) offset in bits
0, # flags
None, # derived from
[None], # members
0, # runtime languages
None, # base type with vtable pointer
None, # template parameters
None # unique identifier
])
return self.emit_debug_info("DISubroutineType", {
"types": self.emit_metadata([None])
})

@memoize
def emit_subprogram(self, func, llfunc):
source_buffer = func.loc.source_buffer
display_name = "{}{}".format(func.name, types.TypePrinter().name(func.type))
subprogram = self.emit([
DW_TAG_subprogram,
self.emit_filename(source_buffer), # filename
self.emit_file(source_buffer), # context descriptor
func.name, # name
display_name, # display name
llfunc.name, # linkage name
func.loc.line(), # line number where defined
self.emit_subroutine_type(func.type), # type descriptor
func.is_internal, # local to compile unit?
True, # global is defined in the compile unit?
0, # virtuality
0, # index into a virtual function
None, # base type with vtable pointer
0, # flags
False, # optimized?
llfunc, # LLVM function
None, # template parameters
None, # function declaration descriptor
[], # function variables
func.loc.line(), # line number where scope begins
])
self.subprograms.append(subprogram)
return subprogram
llsubprogram = self.emit_debug_info("DISubprogram", {
"name": func.name,
"linkageName": llfunc.name,
"type": self.emit_subroutine_type(func.type),
"file": self.emit_file(source_buffer),
"line": func.loc.line(),
"scope": self.emit_file(source_buffer),
"scopeLine": func.loc.line(),
"isLocal": func.is_internal,
"isDefinition": True,
"variables": self.emit_metadata([])
}, is_distinct=True)
self.llsubprograms.append(llsubprogram)
return llsubprogram

@memoize
def emit_loc(self, loc, scope, inlined_scope=None):
return self.emit([
loc.line(), # line
loc.column(), # column
scope, # scope
inlined_scope, # inlined scope
])
def emit_loc(self, loc, scope):
return self.emit_debug_info("DILocation", {
"line": loc.line(),
"column": loc.column(),
"scope": scope
})

def finalize(self, source_buffer):
llident = self.llmodule.add_named_metadata('llvm.ident')
llident.add(self.emit(["ARTIQ"]))
llident.add(self.emit_metadata(["ARTIQ"]))

llflags = self.llmodule.add_named_metadata('llvm.module.flags')
llflags.add(self.emit([2, "Debug Info Version", 1]))
llflags.add(self.emit_metadata([2, "Debug Info Version", 3]))
llflags.add(self.emit_metadata([2, "Dwarf Version", 4]))

llcompile_units = self.llmodule.add_named_metadata('llvm.dbg.cu')
llcompile_units.add(self.emit_compile_unit(source_buffer, tuple(self.subprograms)))
llcompile_units.add(self.emit_compile_unit(source_buffer, tuple(self.llsubprograms)))


class LLVMIRGenerator:
@@ -191,6 +154,10 @@ def __init__(self, engine, module_name, target, function_map, object_map, type_m
self.tbaa_tree,
ll.Constant(lli64, 1)
])
self.tbaa_now = self.llmodule.add_metadata([
ll.MetaDataString(self.llmodule, "timeline position"),
self.tbaa_tree
])

def needs_sret(self, lltyp, may_be_large=True):
if isinstance(lltyp, ll.VoidType):
@@ -577,7 +544,9 @@ def process_function(self, func):
self.llbuilder = ll.IRBuilder()
llblock_map = {}

disubprogram = self.debug_info_emitter.emit_subprogram(func, self.llfunction)
if not func.is_generated:
lldisubprogram = self.debug_info_emitter.emit_subprogram(func, self.llfunction)
self.llfunction.set_metadata('dbg', lldisubprogram)

# First, map arguments.
if self.has_sret(func.type):
@@ -598,9 +567,9 @@ def process_function(self, func):
for block in func.basic_blocks:
self.llbuilder.position_at_end(self.llmap[block])
for insn in block.instructions:
if insn.loc is not None:
if insn.loc is not None and not func.is_generated:
self.llbuilder.debug_metadata = \
self.debug_info_emitter.emit_loc(insn.loc, disubprogram)
self.debug_info_emitter.emit_loc(insn.loc, lldisubprogram)

llinsn = getattr(self, "process_" + type(insn).__name__)(insn)
assert llinsn is not None
@@ -683,15 +652,15 @@ def llptr_to_var(self, llenv, env_ty, var_name, var_type=None):
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)],
inbounds=True)
llouterenv = self.llbuilder.load(llptr)
llouterenv.metadata['invariant.load'] = self.empty_metadata
llouterenv.metadata['nonnull'] = self.empty_metadata
llouterenv.set_metadata('invariant.load', self.empty_metadata)
llouterenv.set_metadata('nonnull', self.empty_metadata)
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)

def mark_dereferenceable(self, load):
assert isinstance(load, ll.LoadInstr) and isinstance(load.type, ll.PointerType)
pointee_size = load.type.pointee.get_abi_size(self.lldatalayout, context=self.llcontext)
metadata = self.llmodule.add_metadata([ll.Constant(lli64, pointee_size)])
load.metadata['dereferenceable'] = metadata
load.set_metadata('dereferenceable', metadata)

def process_GetLocal(self, insn):
env = insn.environment()
@@ -821,7 +790,7 @@ def process_GetAttr(self, insn):
inbounds=True, name="ptr.{}".format(insn.name))
llvalue = self.llbuilder.load(llptr, name="val.{}".format(insn.name))
if types.is_instance(typ) and attr in typ.constant_attributes:
llvalue.metadata['invariant.load'] = self.empty_metadata
llvalue.set_metadata('invariant.load', self.empty_metadata)
if isinstance(llvalue.type, ll.PointerType):
self.mark_dereferenceable(llvalue)
return llvalue
@@ -1065,8 +1034,8 @@ def get_outer(llenv, env_ty):
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)],
inbounds=True)
llouterenv = self.llbuilder.load(llptr)
llouterenv.metadata['invariant.load'] = self.empty_metadata
llouterenv.metadata['nonnull'] = self.empty_metadata
llouterenv.set_metadata('invariant.load', self.empty_metadata)
llouterenv.set_metadata('nonnull', self.empty_metadata)
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
else:
return llenv
@@ -1086,16 +1055,21 @@ def get_outer(llenv, env_ty):
# This is an identity cast at LLVM IR level.
return self.map(insn.operands[0])
elif insn.op == "now_mu":
return self.llbuilder.load(self.llbuiltin("now"), name=insn.name)
llnow = self.llbuilder.load(self.llbuiltin("now"), name=insn.name)
llnow.set_metadata("tbaa", self.tbaa_now)
return llnow
elif insn.op == "at_mu":
time, = insn.operands
return self.llbuilder.store(self.map(time), self.llbuiltin("now"))
elif insn.op == "delay_mu":
interval, = insn.operands
llnowptr = self.llbuiltin("now")
llnow = self.llbuilder.load(llnowptr, name="now.old")
llnow.set_metadata("tbaa", self.tbaa_now)
lladjusted = self.llbuilder.add(llnow, self.map(interval), name="now.new")
return self.llbuilder.store(lladjusted, llnowptr)
llnowstore = self.llbuilder.store(lladjusted, llnowptr)
llnowstore.set_metadata("tbaa", self.tbaa_now)
return llnowstore
elif insn.op == "watchdog_set":
interval, = insn.operands
return self.llbuilder.call(self.llbuiltin("watchdog_set"), [self.map(interval)])
@@ -1325,7 +1299,7 @@ def process_Call(self, insn):
# Never add TBAA nowrite metadata to a functon with sret!
# This leads to miscompilations.
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
llcall.metadata['tbaa'] = self.tbaa_nowrite_call
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)

return llresult

@@ -1358,7 +1332,7 @@ def process_Invoke(self, insn):

# See the comment in process_Call.
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
llcall.metadata['tbaa'] = self.tbaa_nowrite_call
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)

return llcall

2 changes: 1 addition & 1 deletion artiq/coredevice/exceptions.py
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ def __str__(self):
elif address == last_address:
formatted_address = " (inlined)"
else:
formatted_address = " (RA=0x{:x})".format(address)
formatted_address = " (RA=+0x{:x})".format(address)
last_address = address

filename = filename.replace(artiq_dir, "<artiq>")
6 changes: 6 additions & 0 deletions artiq/coredevice/ttl.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@ class TTLOut:
:param channel: channel number
"""
kernel_constant_attributes = {"core", "channel"}

def __init__(self, dmgr, channel, core_device="core"):
self.core = dmgr.get(core_device)
self.channel = channel
@@ -82,6 +84,8 @@ class TTLInOut:
:param channel: channel number
"""
kernel_constant_attributes = {"core", "channel"}

def __init__(self, dmgr, channel, core_device="core"):
self.core = dmgr.get(core_device)
self.channel = channel
@@ -232,6 +236,8 @@ class TTLClockGen:
:param channel: channel number
"""
kernel_constant_attributes = {"core", "channel", "acc_width"}

def __init__(self, dmgr, channel, core_device="core"):
self.core = dmgr.get(core_device)
self.channel = channel
2 changes: 1 addition & 1 deletion conda/artiq/meta.yaml
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ requirements:
- binutils-or1k-linux
run:
- python >=3.5.1
- llvmlite-artiq 0.10.0.dev py35_21
- llvmlite-artiq 0.10.0.dev py35_22
- scipy
- numpy
- prettytable