diff --git a/artiq/coredevice/comm_kernel.py b/artiq/coredevice/comm_kernel.py index 6a342013b6..2fb4a68297 100644 --- a/artiq/coredevice/comm_kernel.py +++ b/artiq/coredevice/comm_kernel.py @@ -228,11 +228,11 @@ def append_backtrace(self, record, inlined=False): format(file=filename, line=line, function=function, address=formatted_address)) else: - lines.append(" {}^".format(" " * (column - indentation))) + lines.append(" {}^".format(" " * (column - indentation - 1))) lines.append(" {}".format(source_line.strip() if source_line else "")) lines.append(" File \"{file}\", line {line}, column {column}," " in {function}{address}". - format(file=filename, line=line, column=column + 1, + format(file=filename, line=line, column=column, function=function, address=formatted_address)) return lines diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 6159c9c003..938c5da2c1 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -9,6 +9,7 @@ from typing import _GenericAlias, Generic, Literal, TypeVar import nac3artiq +import nac3tools from artiq.language.core import * from artiq.language.core import _ConstGenericMarker @@ -240,7 +241,7 @@ def close(self): """ self.comm.close() - def compile(self, method, args, kwargs, embedding_map, file_output=None, target=None): + def compile(self, method, args, kwargs, embedding_map, file_output=None, debug_output=None, target=None): if target is not None: # NAC3TODO: subkernels raise NotImplementedError @@ -264,24 +265,24 @@ def compile(self, method, args, kwargs, embedding_map, file_output=None, target= if file_output is None: return self.compiler.compile_method_to_mem(obj, name, args, embedding_map) else: - self.compiler.compile_method_to_file(obj, name, args, file_output, embedding_map) + self.compiler.compile_method_to_file(obj, name, args, file_output, debug_output, embedding_map) def run(self, function, args, kwargs): embedding_map = EmbeddingMap() - kernel_library = self.compile(function, args, kwargs, embedding_map) + kernel_library, debug_object = self.compile(function, args, kwargs, embedding_map) - self._run_compiled(kernel_library, embedding_map) + self._run_compiled(kernel_library, debug_object, embedding_map) # set by NAC3 if embedding_map.expects_return: return embedding_map.return_value - def _run_compiled(self, kernel_library, embedding_map): + def _run_compiled(self, kernel_library, debug_object, embedding_map): if self.first_run: self.comm.check_system_info() self.first_run = False - symbolizer = lambda addresses: symbolize(kernel_library, addresses) + symbolizer = lambda addresses: symbolize(debug_object, addresses) self.comm.load(kernel_library) self.comm.run() @@ -468,41 +469,29 @@ def symbolize(library, addresses): # inside the call instruction (or its delay slot), since that's what # the backtrace entry should point at. last_inlined = None - offset_addresses = [hex(addr - 1) for addr in addresses] - with RunTool(["llvm-addr2line", "--addresses", "--functions", "--inlines", - "--demangle", "--exe={library}"] + offset_addresses, - library=library) \ - as results: - lines = iter(results["__stdout__"].read().rstrip().split("\n")) - backtrace = [] - while True: - try: - address_or_function = next(lines) - except StopIteration: - break - if address_or_function[:2] == "0x": - address = int(address_or_function[2:], 16) + 1 # remove offset - function = next(lines) - inlined = False - else: - address = backtrace[-1][4] # inlined - function = address_or_function - inlined = True - location = next(lines) - - filename, line = location.rsplit(":", 1) - if filename == "??" or filename == "": - continue - if line == "?": - line = -1 - else: - line = int(line) - # can't get column out of addr2line D: - if inlined: - last_inlined.append((filename, line, -1, function, address)) - else: - last_inlined = [] - backtrace.append((filename, line, -1, function, address, - last_inlined)) - return backtrace + offset_addresses = [addr - 1 for addr in addresses] + call_records = nac3tools.symbolize(library, offset_addresses) + backtrace = [] + for record in call_records: + address = record.address + inlined = False + if address is None: + address = backtrace[-1][4] # inlined + inlined = True + else: + address += 1 + filename = record.file + dirname = record.dir + if dirname is not None: + filename = dirname + "/" + filename + function, line, column = record.name, record.line, record.column + + if inlined: + last_inlined.append((filename, line, column, function, address)) + else: + last_inlined = [] + backtrace.append((filename, line, column, function, address, + last_inlined)) + + return backtrace diff --git a/artiq/frontend/artiq_compile.py b/artiq/frontend/artiq_compile.py index 1f202f8610..fa1329eb6a 100755 --- a/artiq/frontend/artiq_compile.py +++ b/artiq/frontend/artiq_compile.py @@ -32,6 +32,8 @@ def get_argparser(): parser.add_argument("-o", "--output", default=None, help="output file") + parser.add_argument("-d", "--debug", default=None, + help="debug file") parser.add_argument("file", metavar="FILE", help="file containing the experiment to compile") parser.add_argument("arguments", metavar="ARGUMENTS", @@ -65,7 +67,7 @@ def main(): if not getattr(exp.run, "__artiq_kernel__", False): raise ValueError("Experiment entry point must be a kernel") - exp_inst.core.compile(exp_inst.run, [], {}, embedding_map, file_output=output) + exp_inst.core.compile(exp_inst.run, [], {}, embedding_map, file_output=output, debug_output=args.debug) finally: dataset_db.close_db() finally: