Debug Location Info #267

Merged
sb10q merged 1 commits from debug_info into master 2024-08-17 17:37:19 +08:00
Collaborator

Added the debug location info needed to show the backtrace.

Tested on devices with some common cases except for this bug which I did not find manage to find the cause yet...

this code works fine:

from artiq.experiment import *
from numpy import int32
from artiq.coredevice.exceptions import *
from artiq.coredevice.core import Core
from artiq.coredevice.ttl import TTLOut
from typing import TypeVar

@nac3
class A:
        a: Kernel[int32]
            
        @kernel
        def __init__(self, a: int32):
            self.a = a

        @kernel
        def info(self) -> int32:
            output(self.a)
            return self.a + 4

lll = [4,5,1,8]

@nac3
class IdleKernel(EnvExperiment):
    core: KernelInvariant[Core]
    led0: KernelInvariant[TTLOut]
    def build(self):
        self.setattr_device("core")
        self.setattr_device("led0")
    
    @kernel
    def run(self):
        aa = [Some(A(i)) if i > 3 else none for i in lll]
        for aaa in aa:
            ddd = aaa.unwrap().info()
            output(ddd)
        try:
            a = [1]
            a[100] = 1
        except:
            output(999)
            raise ValueError("ss")

        
T = TypeVar('T')
@rpc
def output(t: T):
    print(t)

gives:

4
8
5
9
Core Device Traceback:
Traceback (most recent call first):
  File "info_2.py", line 51, column 30, in artiq_run_info_2.IdleKernel.run.0
    ddd = aaa.unwrap().info()
                     ^
  File "./__nac3_synthesized_modinit__", line 2, in __modinit__ (RA=+0xe4)
    <unknown> 
  File "./info_2.py", line 51, in artiq_run_info_2.IdleKernel.run.0 (RA=+0x348)
    ddd = aaa.unwrap().info()
UnwrapNoneError(0):

but if we specify the type of the exception by except IndexError:

modified code
from artiq.experiment import *
from numpy import int32
from artiq.coredevice.exceptions import *
from artiq.coredevice.core import Core
from artiq.coredevice.ttl import TTLOut
from typing import TypeVar

@nac3
class A:
        a: Kernel[int32]
            
        @kernel
        def __init__(self, a: int32):
            self.a = a

        @kernel
        def info(self) -> int32:
            output(self.a)
            return self.a + 4

lll = [4,5,1,8]

@nac3
class IdleKernel(EnvExperiment):
    core: KernelInvariant[Core]
    led0: KernelInvariant[TTLOut]
    def build(self):
        self.setattr_device("core")
        self.setattr_device("led0")
    
    @kernel
    def run(self):
        aa = [Some(A(i)) if i > 3 else none for i in lll]
        for aaa in aa:
            ddd = aaa.unwrap().info()
            output(ddd)
        try:
            a = [1]
            a[100] = 1
        except IndexError:
            output(999)
            raise ValueError("ss")

        
T = TypeVar('T')
@rpc
def output(t: T):
    print(t)

the traceback will fail to give correct line number and the source code information:

4
8
5
9
Core Device Traceback:
Traceback (most recent call first):
  File "info_2.py", line 51, column 30, in artiq_run_info_2.IdleKernel.run.0
    ddd = aaa.unwrap().info()
                     ^
  File "./__nac3_synthesized_modinit__", line 2, in __modinit__ (RA=+0xe4)
    <unknown>
  File "./info_2.py", line 0, in artiq_run_info_2.IdleKernel.run.0 (RA=+0x40c)
    <unknown>
UnwrapNoneError(0):
Added the debug location info needed to show the backtrace. Tested on devices with some common cases except for this bug which I did not find manage to find the cause yet... this code works fine: ```python from artiq.experiment import * from numpy import int32 from artiq.coredevice.exceptions import * from artiq.coredevice.core import Core from artiq.coredevice.ttl import TTLOut from typing import TypeVar @nac3 class A: a: Kernel[int32] @kernel def __init__(self, a: int32): self.a = a @kernel def info(self) -> int32: output(self.a) return self.a + 4 lll = [4,5,1,8] @nac3 class IdleKernel(EnvExperiment): core: KernelInvariant[Core] led0: KernelInvariant[TTLOut] def build(self): self.setattr_device("core") self.setattr_device("led0") @kernel def run(self): aa = [Some(A(i)) if i > 3 else none for i in lll] for aaa in aa: ddd = aaa.unwrap().info() output(ddd) try: a = [1] a[100] = 1 except: output(999) raise ValueError("ss") T = TypeVar('T') @rpc def output(t: T): print(t) ``` gives: ``` 4 8 5 9 Core Device Traceback: Traceback (most recent call first): File "info_2.py", line 51, column 30, in artiq_run_info_2.IdleKernel.run.0 ddd = aaa.unwrap().info() ^ File "./__nac3_synthesized_modinit__", line 2, in __modinit__ (RA=+0xe4) <unknown> File "./info_2.py", line 51, in artiq_run_info_2.IdleKernel.run.0 (RA=+0x348) ddd = aaa.unwrap().info() UnwrapNoneError(0): ``` but if we specify the type of the exception by `except IndexError:` <details> <summary> modified code </summary> ```python from artiq.experiment import * from numpy import int32 from artiq.coredevice.exceptions import * from artiq.coredevice.core import Core from artiq.coredevice.ttl import TTLOut from typing import TypeVar @nac3 class A: a: Kernel[int32] @kernel def __init__(self, a: int32): self.a = a @kernel def info(self) -> int32: output(self.a) return self.a + 4 lll = [4,5,1,8] @nac3 class IdleKernel(EnvExperiment): core: KernelInvariant[Core] led0: KernelInvariant[TTLOut] def build(self): self.setattr_device("core") self.setattr_device("led0") @kernel def run(self): aa = [Some(A(i)) if i > 3 else none for i in lll] for aaa in aa: ddd = aaa.unwrap().info() output(ddd) try: a = [1] a[100] = 1 except IndexError: output(999) raise ValueError("ss") T = TypeVar('T') @rpc def output(t: T): print(t) ``` </details> the traceback will fail to give correct line number and the source code information: ``` 4 8 5 9 Core Device Traceback: Traceback (most recent call first): File "info_2.py", line 51, column 30, in artiq_run_info_2.IdleKernel.run.0 ddd = aaa.unwrap().info() ^ File "./__nac3_synthesized_modinit__", line 2, in __modinit__ (RA=+0xe4) <unknown> File "./info_2.py", line 0, in artiq_run_info_2.IdleKernel.run.0 (RA=+0x40c) <unknown> UnwrapNoneError(0): ```
Owner

File "./__nac3_synthesized_modinit__",

AFAIK the "standard" in Python would be <nac3_synthesized_modinit>

> ``File "./__nac3_synthesized_modinit__",`` AFAIK the "standard" in Python would be ``<nac3_synthesized_modinit>``
Author
Collaborator

Hmm despite some more trails with the code that users may write (among which some can and some cannot produce the valid location info in traceback), it seems that the problem is with the llvm optimization when lowering to target platform specific binaries?

for the following more minimized code:

@nac3
class A:
    a: Kernel[int32]
    
    @kernel
    def __init__(self, a: int32):
        self.a = a

    @kernel
    def info(self) -> int32:
        print_int32(self.a)
        return self.a + 4

lll = [4,5,1,2]

@nac3
class Demo:
    core: KernelInvariant[Core]
    def __init__(self):
         self.core = Core()
        
    @kernel
    def run(self):
        aa = [Some(A(i)) if i > 3 else none for i in lll]
        aa[2].unwrap().info()
        try:
            aa[100]
        except IndexError:
            raise ValueError("99")

the optimized IR can be generated with desired debug location info:

optimized IR
; ModuleID = 'main'
source_filename = "main"

%__main__.Demo = type { %min_artiq.Core* }
%min_artiq.Core = type { double }
%__main__.A = type { i32 }
%Exception = type { i32, %str, i32, i32, %str, %str, i64, i64, i64 }
%str = type { i8*, i64 }

@"139874046227264_" = global [4 x i32] [i32 4, i32 5, i32 1, i32 2]
@const = private unnamed_addr constant [30 x i8] c"index {0} out of bounds 0:{1}\00", align 1
@const.1 = private unnamed_addr constant [63 x i8] c"/home/cresc/code/nac3/work1/nac3/my_expr/artiq/./debug_info.py\00", align 1
@const.2 = private unnamed_addr constant [20 x i8] c"__main__.Demo.run.0\00", align 1
@const.3 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@exn.9 = global i32 9
@const.6 = private unnamed_addr constant [3 x i8] c"99\00", align 1
@"139876328321664" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"139876328321472" }
@"139874046227264" = global { i32*, i64 } { i32* getelementptr inbounds ([4 x i32], [4 x i32]* @"139874046227264_", i32 0, i32 0), i64 4 }
@"139876328321472" = global %min_artiq.Core { double 1.000000e-09 }
@tagptr0 = private global [4 x i8] c"li:n"
@"9595260818115849311" = private global { i8*, i64 } { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @tagptr0, i32 0, i32 0), i64 4 }

define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality !dbg !9 {
init:
  %argptr.i = alloca i8*, align 8
  %rpc.arg0.i = alloca { i32*, i64 }*, align 8
  tail call fastcc void @__main__.Demo.run.0(), !dbg !13
  %0 = bitcast i8** %argptr.i to i8*, !dbg !13
  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0), !dbg !13
  %1 = bitcast { i32*, i64 }** %rpc.arg0.i to i8*, !dbg !13
  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %1), !dbg !13
  %rpc.stack.i = tail call i8* @llvm.stacksave(), !dbg !13
  store { i32*, i64 }* @"139874046227264", { i32*, i64 }** %rpc.arg0.i, align 8, !dbg !13
  %2 = bitcast i8** %argptr.i to { i32*, i64 }***, !dbg !13
  store { i32*, i64 }** %rpc.arg0.i, { i32*, i64 }*** %2, align 8, !dbg !13
  call void @rpc_send(i32 0, { i8*, i64 }* nonnull @"9595260818115849311", i8** nonnull %argptr.i), !dbg !13
  call void @llvm.stackrestore(i8* %rpc.stack.i), !dbg !13
  %rpc_recv.i = call i32 @rpc_recv(i8* null), !dbg !13
  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0), !dbg !13
  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %1), !dbg !13
  ret void, !dbg !13
}

declare i32 @__nac3_personality(...)

declare void @print_int32(i32) local_unnamed_addr

define private fastcc void @__main__.Demo.run.0() unnamed_addr personality i32 (...)* @__nac3_personality !dbg !15 {
init:
  %load = load i64, i64* getelementptr inbounds ({ i32*, i64 }, { i32*, i64 }* @"139874046227264", i64 0, i32 1), align 8
  %tmparr = alloca %__main__.A**, i64 %load, align 8
  %load4 = load i32*, i32** getelementptr inbounds ({ i32*, i64 }, { i32*, i64 }* @"139874046227264", i64 0, i32 0), align 8
  %cmp17 = icmp sgt i64 %load, 0
  br i1 %cmp17, label %body1, label %fail

body1:                                            ; preds = %init, %cont10
  %inc19 = phi i64 [ %inc, %cont10 ], [ 0, %init ]
  %gep5 = getelementptr i32, i32* %load4, i64 %inc19
  %load6 = load i32, i32* %gep5, align 4
  %cmp9 = icmp sgt i32 %load6, 3, !dbg !16
  br i1 %cmp9, label %then, label %cont10, !dbg !16

cont:                                             ; preds = %cont10
  %inbound = icmp ugt i64 %load, 2, !dbg !18
  br i1 %inbound, label %succ, label %fail, !dbg !18, !prof !19

then:                                             ; preds = %body1
  %alloca = alloca %__main__.A, align 8, !dbg !20
  %attr.i = getelementptr inbounds %__main__.A, %__main__.A* %alloca, i64 0, i32 0, !dbg !21
  store i32 %load6, i32* %attr.i, align 8, !dbg !21
  %alloca_some = alloca %__main__.A*, align 8, !dbg !20
  store %__main__.A* %alloca, %__main__.A** %alloca_some, align 8, !dbg !20
  br label %cont10, !dbg !20

cont10:                                           ; preds = %body1, %then
  %storemerge = phi %__main__.A** [ %alloca_some, %then ], [ null, %body1 ], !dbg !25
  %elem_ptr = getelementptr %__main__.A**, %__main__.A*** %tmparr, i64 %inc19, !dbg !26
  store %__main__.A** %storemerge, %__main__.A*** %elem_ptr, align 8, !dbg !26
  %inc = add nuw nsw i64 %inc19, 1
  %cmp = icmp slt i64 %inc, %load
  br i1 %cmp, label %body1, label %cont

succ:                                             ; preds = %cont
  %gep24 = getelementptr %__main__.A**, %__main__.A*** %tmparr, i64 2, !dbg !18
  %load25 = load %__main__.A**, %__main__.A*** %gep24, align 8, !dbg !18
  %unwrap_not_null.not = icmp eq %__main__.A** %load25, null, !dbg !18
  br i1 %unwrap_not_null.not, label %fail28, label %succ27, !dbg !18, !prof !27

fail:                                             ; preds = %init, %cont
  %tmp.0.lcssa22 = phi i64 [ %load, %cont ], [ 0, %init ]
  %alloca21 = alloca %Exception, align 8, !dbg !18
  %exn.id = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 0, !dbg !18
  store i32 9, i32* %exn.id, align 8, !dbg !18
  %exn.msg.repack = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 5, i32 0, !dbg !18
  store i8* getelementptr inbounds ([30 x i8], [30 x i8]* @const, i64 0, i64 0), i8** %exn.msg.repack, align 8, !dbg !18
  %exn.msg.repack1 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 5, i32 1, !dbg !18
  store i64 29, i64* %exn.msg.repack1, align 8, !dbg !18
  %exn.param = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 6, !dbg !18
  store i64 2, i64* %exn.param, align 8, !dbg !18
  %exn.param22 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 7, !dbg !18
  store i64 %tmp.0.lcssa22, i64* %exn.param22, align 8, !dbg !18
  %exn.param23 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 8, !dbg !18
  store i64 0, i64* %exn.param23, align 8, !dbg !18
  %file_ptr.repack = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 1, i32 0, !dbg !18
  store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %file_ptr.repack, align 8, !dbg !18
  %file_ptr.repack2 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 1, i32 1, !dbg !18
  store i64 62, i64* %file_ptr.repack2, align 8, !dbg !18
  %row_ptr = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 2, !dbg !18
  store i32 30, i32* %row_ptr, align 8, !dbg !18
  %col_ptr = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 3, !dbg !18
  store i32 11, i32* %col_ptr, align 4, !dbg !18
  %name_ptr.repack = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 4, i32 0, !dbg !18
  store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %name_ptr.repack, align 8, !dbg !18
  %name_ptr.repack3 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 4, i32 1, !dbg !18
  store i64 19, i64* %name_ptr.repack3, align 8, !dbg !18
  call void @__nac3_raise(%Exception* nonnull %alloca21), !dbg !18
  unreachable, !dbg !18

succ27:                                           ; preds = %succ
  %unwrap_some_load = load %__main__.A*, %__main__.A** %load25, align 8, !dbg !18
  %unwrap_some_load.idx = getelementptr %__main__.A, %__main__.A* %unwrap_some_load, i64 0, i32 0, !dbg !18
  %unwrap_some_load.idx.val = load i32, i32* %unwrap_some_load.idx, align 4, !dbg !18
  call void @print_int32(i32 %unwrap_some_load.idx.val), !dbg !28
  %inbound46 = icmp ugt i64 %load, 100, !dbg !32
  br i1 %inbound46, label %succ48, label %fail49, !dbg !32, !prof !19

fail28:                                           ; preds = %succ
  %alloca29 = alloca %Exception, align 8, !dbg !18
  %exn.id30 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 0, !dbg !18
  store i32 10, i32* %exn.id30, align 8, !dbg !18
  %exn.msg31.repack = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 5, i32 0, !dbg !18
  store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @const.3, i64 0, i64 0), i8** %exn.msg31.repack, align 8, !dbg !18
  %exn.msg31.repack4 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 5, i32 1, !dbg !18
  %file_ptr35.repack = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 1, i32 0, !dbg !18
  %0 = bitcast i64* %exn.msg31.repack4 to i8*, !dbg !18
  call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(32) %0, i8 0, i64 32, i1 false), !dbg !18
  store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %file_ptr35.repack, align 8, !dbg !18
  %file_ptr35.repack5 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 1, i32 1, !dbg !18
  store i64 62, i64* %file_ptr35.repack5, align 8, !dbg !18
  %row_ptr36 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 2, !dbg !18
  store i32 30, i32* %row_ptr36, align 8, !dbg !18
  %col_ptr37 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 3, !dbg !18
  store i32 21, i32* %col_ptr37, align 4, !dbg !18
  %name_ptr38.repack = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 4, i32 0, !dbg !18
  store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %name_ptr38.repack, align 8, !dbg !18
  %name_ptr38.repack6 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 4, i32 1, !dbg !18
  store i64 19, i64* %name_ptr38.repack6, align 8, !dbg !18
  call void @__nac3_raise(%Exception* nonnull %alloca29), !dbg !18
  unreachable, !dbg !18

try.landingpad:                                   ; preds = %fail49
  %try.landingpad74 = landingpad { i8*, %Exception* }
          catch i32* @exn.9, !dbg !33
  %exn75 = extractvalue { i8*, %Exception* } %try.landingpad74, 1, !dbg !33
  %exnidptr = getelementptr %Exception, %Exception* %exn75, i64 0, i32 0, !dbg !32
  %exnid = load i32, i32* %exnidptr, align 4, !dbg !32
  %expected_id = load i32, i32* @exn.9, align 4, !dbg !33
  %exncheck = icmp eq i32 %exnid, %expected_id, !dbg !33
  br i1 %exncheck, label %try.handler, label %try.dispatcher_cont, !dbg !33

succ48:                                           ; preds = %succ27
  ret void, !dbg !33

fail49:                                           ; preds = %succ27
  %alloca50 = alloca %Exception, align 8, !dbg !32
  %exn.id51 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 0, !dbg !32
  store i32 9, i32* %exn.id51, align 8, !dbg !32
  %exn.msg52.repack = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 5, i32 0, !dbg !32
  store i8* getelementptr inbounds ([30 x i8], [30 x i8]* @const, i64 0, i64 0), i8** %exn.msg52.repack, align 8, !dbg !32
  %exn.msg52.repack7 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 5, i32 1, !dbg !32
  store i64 29, i64* %exn.msg52.repack7, align 8, !dbg !32
  %exn.param53 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 6, !dbg !32
  store i64 100, i64* %exn.param53, align 8, !dbg !32
  %exn.param54 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 7, !dbg !32
  store i64 %load, i64* %exn.param54, align 8, !dbg !32
  %exn.param55 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 8, !dbg !32
  store i64 0, i64* %exn.param55, align 8, !dbg !32
  %file_ptr56.repack = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 1, i32 0, !dbg !32
  store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %file_ptr56.repack, align 8, !dbg !32
  %file_ptr56.repack8 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 1, i32 1, !dbg !32
  store i64 62, i64* %file_ptr56.repack8, align 8, !dbg !32
  %row_ptr57 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 2, !dbg !32
  store i32 32, i32* %row_ptr57, align 8, !dbg !32
  %col_ptr58 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 3, !dbg !32
  store i32 15, i32* %col_ptr58, align 4, !dbg !32
  %name_ptr59.repack = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 4, i32 0, !dbg !32
  store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %name_ptr59.repack, align 8, !dbg !32
  %name_ptr59.repack9 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 4, i32 1, !dbg !32
  store i64 19, i64* %name_ptr59.repack9, align 8, !dbg !32
  invoke void @__nac3_raise(%Exception* nonnull %alloca50)
          to label %after.raise unwind label %try.landingpad, !dbg !32

after.raise:                                      ; preds = %fail49
  unreachable, !dbg !32

try.handler:                                      ; preds = %try.landingpad
  %alloca62 = alloca %Exception, align 8, !dbg !33
  %exn.id63 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 0, !dbg !33
  store i32 11, i32* %exn.id63, align 8, !dbg !33
  %exn.msg64.repack = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 5, i32 0, !dbg !33
  store i8* getelementptr inbounds ([3 x i8], [3 x i8]* @const.6, i64 0, i64 0), i8** %exn.msg64.repack, align 8, !dbg !33
  %exn.msg64.repack10 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 5, i32 1, !dbg !33
  store i64 2, i64* %exn.msg64.repack10, align 8, !dbg !33
  %exn.param65 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 6, !dbg !33
  %exn.str.repack = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 1, i32 0, !dbg !33
  %1 = bitcast i64* %exn.param65 to i8*, !dbg !33
  call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(24) %1, i8 0, i64 24, i1 false), !dbg !33
  %exn.str.repack11 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 1, i32 1, !dbg !33
  %exn.str68.repack = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 4, i32 0, !dbg !33
  %exn.str68.repack12 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 4, i32 1, !dbg !33
  %exn.ints = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 2, !dbg !33
  %exn.ints69 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 3, !dbg !33
  store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %exn.str.repack, align 8, !dbg !33
  store i64 62, i64* %exn.str.repack11, align 8, !dbg !33
  store i32 34, i32* %exn.ints, align 8, !dbg !33
  store i32 13, i32* %exn.ints69, align 4, !dbg !33
  store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %exn.str68.repack, align 8, !dbg !33
  store i64 19, i64* %exn.str68.repack12, align 8, !dbg !33
  call void @__nac3_raise(%Exception* nonnull %alloca62), !dbg !33
  unreachable, !dbg !33

try.dispatcher_cont:                              ; preds = %try.landingpad
  call void @__nac3_resume(), !dbg !33
  unreachable, !dbg !33
}

; Function Attrs: noreturn
declare void @__nac3_raise(%Exception*) local_unnamed_addr #0

; Function Attrs: noreturn
declare void @__nac3_resume() local_unnamed_addr #0

; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare i8* @llvm.stacksave() #1

declare void @rpc_send(i32, { i8*, i64 }*, i8**) local_unnamed_addr

; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare void @llvm.stackrestore(i8*) #1

declare i32 @rpc_recv(i8*) local_unnamed_addr

; Function Attrs: argmemonly nofree nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #2

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #3

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #3

attributes #0 = { noreturn }
attributes #1 = { mustprogress nofree nosync nounwind willreturn }
attributes #2 = { argmemonly nofree nounwind willreturn writeonly }
attributes #3 = { argmemonly nofree nosync nounwind willreturn }

!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2, !5, !7, !8}

!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 2, !"Dwarf Version", i32 4}
!2 = distinct !DICompileUnit(language: DW_LANG_Python, file: !3, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false)
!3 = !DIFile(filename: "<nac3_synthesized_modinit>", directory: ".")
!4 = !{}
!5 = distinct !DICompileUnit(language: DW_LANG_Python, file: !6, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false)
!6 = !DIFile(filename: "/home/cresc/code/nac3/work1/nac3/my_expr/artiq/./debug_info.py", directory: ".")
!7 = distinct !DICompileUnit(language: DW_LANG_Python, file: !6, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false)
!8 = distinct !DICompileUnit(language: DW_LANG_Python, file: !6, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false)
!9 = distinct !DISubprogram(name: "__modinit__", linkageName: "__modinit__", scope: null, file: !3, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !4)
!10 = !DISubroutineType(flags: DIFlagPublic, types: !11)
!11 = !{!12}
!12 = !DIBasicType(name: "_", flags: DIFlagPublic)
!13 = !DILocation(line: 2, column: 5, scope: !14)
!14 = distinct !DILexicalBlock(scope: !9, file: !3, line: 2, column: 5)
!15 = distinct !DISubprogram(name: "__main__.Demo.run.0", linkageName: "__main__.Demo.run.0", scope: null, file: !6, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !8, retainedNodes: !4)
!16 = !DILocation(line: 29, column: 33, scope: !17)
!17 = distinct !DILexicalBlock(scope: !15, file: !6, line: 29, column: 9)
!18 = !DILocation(line: 30, column: 12, scope: !17)
!19 = !{!"branch_weights", i32 2000, i32 1}
!20 = !DILocation(line: 29, column: 22, scope: !17)
!21 = !DILocation(line: 12, column: 9, scope: !22, inlinedAt: !24)
!22 = distinct !DILexicalBlock(scope: !23, file: !6, line: 12, column: 9)
!23 = distinct !DISubprogram(name: "__main__.A.__init__.0", linkageName: "__main__.A.__init__.0", scope: null, file: !6, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !5, retainedNodes: !4)
!24 = distinct !DILocation(line: 29, column: 22, scope: !17)
!25 = !DILocation(line: 0, scope: !17)
!26 = !DILocation(line: 29, column: 40, scope: !17)
!27 = !{!"branch_weights", i32 1, i32 2000}
!28 = !DILocation(line: 16, column: 21, scope: !29, inlinedAt: !31)
!29 = distinct !DILexicalBlock(scope: !30, file: !6, line: 16, column: 9)
!30 = distinct !DISubprogram(name: "__main__.A.info.0", linkageName: "__main__.A.info.0", scope: null, file: !6, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !7, retainedNodes: !4)
!31 = distinct !DILocation(line: 30, column: 12, scope: !17)
!32 = !DILocation(line: 32, column: 16, scope: !17)
!33 = !DILocation(line: 34, column: 31, scope: !17)

but the traceback will still fail UNLESS we take the following patch to set the optimization level to None (Less does not work, either) when creating target machine:

diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs
index d6ed943..0f88aaf 100644
--- a/nac3artiq/src/lib.rs
+++ b/nac3artiq/src/lib.rs
@@ -847,7 +847,7 @@ impl Nac3 {
                 &triple,
                 "",
                 &features,
-                OptimizationLevel::Default,
+                OptimizationLevel::None,
                 RelocMode::PIC,
                 CodeModel::Default,
             )
Hmm despite some more trails with the code that users may write (among which some can and some cannot produce the valid location info in traceback), it seems that the problem is with the llvm optimization when lowering to target platform specific binaries? for the following more minimized code: ```python @nac3 class A: a: Kernel[int32] @kernel def __init__(self, a: int32): self.a = a @kernel def info(self) -> int32: print_int32(self.a) return self.a + 4 lll = [4,5,1,2] @nac3 class Demo: core: KernelInvariant[Core] def __init__(self): self.core = Core() @kernel def run(self): aa = [Some(A(i)) if i > 3 else none for i in lll] aa[2].unwrap().info() try: aa[100] except IndexError: raise ValueError("99") ``` the optimized IR can be generated with desired debug location info: <details> <summary> optimized IR </summary> ```llvm ; ModuleID = 'main' source_filename = "main" %__main__.Demo = type { %min_artiq.Core* } %min_artiq.Core = type { double } %__main__.A = type { i32 } %Exception = type { i32, %str, i32, i32, %str, %str, i64, i64, i64 } %str = type { i8*, i64 } @"139874046227264_" = global [4 x i32] [i32 4, i32 5, i32 1, i32 2] @const = private unnamed_addr constant [30 x i8] c"index {0} out of bounds 0:{1}\00", align 1 @const.1 = private unnamed_addr constant [63 x i8] c"/home/cresc/code/nac3/work1/nac3/my_expr/artiq/./debug_info.py\00", align 1 @const.2 = private unnamed_addr constant [20 x i8] c"__main__.Demo.run.0\00", align 1 @const.3 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 @exn.9 = global i32 9 @const.6 = private unnamed_addr constant [3 x i8] c"99\00", align 1 @"139876328321664" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"139876328321472" } @"139874046227264" = global { i32*, i64 } { i32* getelementptr inbounds ([4 x i32], [4 x i32]* @"139874046227264_", i32 0, i32 0), i64 4 } @"139876328321472" = global %min_artiq.Core { double 1.000000e-09 } @tagptr0 = private global [4 x i8] c"li:n" @"9595260818115849311" = private global { i8*, i64 } { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @tagptr0, i32 0, i32 0), i64 4 } define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality !dbg !9 { init: %argptr.i = alloca i8*, align 8 %rpc.arg0.i = alloca { i32*, i64 }*, align 8 tail call fastcc void @__main__.Demo.run.0(), !dbg !13 %0 = bitcast i8** %argptr.i to i8*, !dbg !13 call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0), !dbg !13 %1 = bitcast { i32*, i64 }** %rpc.arg0.i to i8*, !dbg !13 call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %1), !dbg !13 %rpc.stack.i = tail call i8* @llvm.stacksave(), !dbg !13 store { i32*, i64 }* @"139874046227264", { i32*, i64 }** %rpc.arg0.i, align 8, !dbg !13 %2 = bitcast i8** %argptr.i to { i32*, i64 }***, !dbg !13 store { i32*, i64 }** %rpc.arg0.i, { i32*, i64 }*** %2, align 8, !dbg !13 call void @rpc_send(i32 0, { i8*, i64 }* nonnull @"9595260818115849311", i8** nonnull %argptr.i), !dbg !13 call void @llvm.stackrestore(i8* %rpc.stack.i), !dbg !13 %rpc_recv.i = call i32 @rpc_recv(i8* null), !dbg !13 call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0), !dbg !13 call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %1), !dbg !13 ret void, !dbg !13 } declare i32 @__nac3_personality(...) declare void @print_int32(i32) local_unnamed_addr define private fastcc void @__main__.Demo.run.0() unnamed_addr personality i32 (...)* @__nac3_personality !dbg !15 { init: %load = load i64, i64* getelementptr inbounds ({ i32*, i64 }, { i32*, i64 }* @"139874046227264", i64 0, i32 1), align 8 %tmparr = alloca %__main__.A**, i64 %load, align 8 %load4 = load i32*, i32** getelementptr inbounds ({ i32*, i64 }, { i32*, i64 }* @"139874046227264", i64 0, i32 0), align 8 %cmp17 = icmp sgt i64 %load, 0 br i1 %cmp17, label %body1, label %fail body1: ; preds = %init, %cont10 %inc19 = phi i64 [ %inc, %cont10 ], [ 0, %init ] %gep5 = getelementptr i32, i32* %load4, i64 %inc19 %load6 = load i32, i32* %gep5, align 4 %cmp9 = icmp sgt i32 %load6, 3, !dbg !16 br i1 %cmp9, label %then, label %cont10, !dbg !16 cont: ; preds = %cont10 %inbound = icmp ugt i64 %load, 2, !dbg !18 br i1 %inbound, label %succ, label %fail, !dbg !18, !prof !19 then: ; preds = %body1 %alloca = alloca %__main__.A, align 8, !dbg !20 %attr.i = getelementptr inbounds %__main__.A, %__main__.A* %alloca, i64 0, i32 0, !dbg !21 store i32 %load6, i32* %attr.i, align 8, !dbg !21 %alloca_some = alloca %__main__.A*, align 8, !dbg !20 store %__main__.A* %alloca, %__main__.A** %alloca_some, align 8, !dbg !20 br label %cont10, !dbg !20 cont10: ; preds = %body1, %then %storemerge = phi %__main__.A** [ %alloca_some, %then ], [ null, %body1 ], !dbg !25 %elem_ptr = getelementptr %__main__.A**, %__main__.A*** %tmparr, i64 %inc19, !dbg !26 store %__main__.A** %storemerge, %__main__.A*** %elem_ptr, align 8, !dbg !26 %inc = add nuw nsw i64 %inc19, 1 %cmp = icmp slt i64 %inc, %load br i1 %cmp, label %body1, label %cont succ: ; preds = %cont %gep24 = getelementptr %__main__.A**, %__main__.A*** %tmparr, i64 2, !dbg !18 %load25 = load %__main__.A**, %__main__.A*** %gep24, align 8, !dbg !18 %unwrap_not_null.not = icmp eq %__main__.A** %load25, null, !dbg !18 br i1 %unwrap_not_null.not, label %fail28, label %succ27, !dbg !18, !prof !27 fail: ; preds = %init, %cont %tmp.0.lcssa22 = phi i64 [ %load, %cont ], [ 0, %init ] %alloca21 = alloca %Exception, align 8, !dbg !18 %exn.id = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 0, !dbg !18 store i32 9, i32* %exn.id, align 8, !dbg !18 %exn.msg.repack = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 5, i32 0, !dbg !18 store i8* getelementptr inbounds ([30 x i8], [30 x i8]* @const, i64 0, i64 0), i8** %exn.msg.repack, align 8, !dbg !18 %exn.msg.repack1 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 5, i32 1, !dbg !18 store i64 29, i64* %exn.msg.repack1, align 8, !dbg !18 %exn.param = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 6, !dbg !18 store i64 2, i64* %exn.param, align 8, !dbg !18 %exn.param22 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 7, !dbg !18 store i64 %tmp.0.lcssa22, i64* %exn.param22, align 8, !dbg !18 %exn.param23 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 8, !dbg !18 store i64 0, i64* %exn.param23, align 8, !dbg !18 %file_ptr.repack = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 1, i32 0, !dbg !18 store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %file_ptr.repack, align 8, !dbg !18 %file_ptr.repack2 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 1, i32 1, !dbg !18 store i64 62, i64* %file_ptr.repack2, align 8, !dbg !18 %row_ptr = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 2, !dbg !18 store i32 30, i32* %row_ptr, align 8, !dbg !18 %col_ptr = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 3, !dbg !18 store i32 11, i32* %col_ptr, align 4, !dbg !18 %name_ptr.repack = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 4, i32 0, !dbg !18 store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %name_ptr.repack, align 8, !dbg !18 %name_ptr.repack3 = getelementptr inbounds %Exception, %Exception* %alloca21, i64 0, i32 4, i32 1, !dbg !18 store i64 19, i64* %name_ptr.repack3, align 8, !dbg !18 call void @__nac3_raise(%Exception* nonnull %alloca21), !dbg !18 unreachable, !dbg !18 succ27: ; preds = %succ %unwrap_some_load = load %__main__.A*, %__main__.A** %load25, align 8, !dbg !18 %unwrap_some_load.idx = getelementptr %__main__.A, %__main__.A* %unwrap_some_load, i64 0, i32 0, !dbg !18 %unwrap_some_load.idx.val = load i32, i32* %unwrap_some_load.idx, align 4, !dbg !18 call void @print_int32(i32 %unwrap_some_load.idx.val), !dbg !28 %inbound46 = icmp ugt i64 %load, 100, !dbg !32 br i1 %inbound46, label %succ48, label %fail49, !dbg !32, !prof !19 fail28: ; preds = %succ %alloca29 = alloca %Exception, align 8, !dbg !18 %exn.id30 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 0, !dbg !18 store i32 10, i32* %exn.id30, align 8, !dbg !18 %exn.msg31.repack = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 5, i32 0, !dbg !18 store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @const.3, i64 0, i64 0), i8** %exn.msg31.repack, align 8, !dbg !18 %exn.msg31.repack4 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 5, i32 1, !dbg !18 %file_ptr35.repack = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 1, i32 0, !dbg !18 %0 = bitcast i64* %exn.msg31.repack4 to i8*, !dbg !18 call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(32) %0, i8 0, i64 32, i1 false), !dbg !18 store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %file_ptr35.repack, align 8, !dbg !18 %file_ptr35.repack5 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 1, i32 1, !dbg !18 store i64 62, i64* %file_ptr35.repack5, align 8, !dbg !18 %row_ptr36 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 2, !dbg !18 store i32 30, i32* %row_ptr36, align 8, !dbg !18 %col_ptr37 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 3, !dbg !18 store i32 21, i32* %col_ptr37, align 4, !dbg !18 %name_ptr38.repack = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 4, i32 0, !dbg !18 store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %name_ptr38.repack, align 8, !dbg !18 %name_ptr38.repack6 = getelementptr inbounds %Exception, %Exception* %alloca29, i64 0, i32 4, i32 1, !dbg !18 store i64 19, i64* %name_ptr38.repack6, align 8, !dbg !18 call void @__nac3_raise(%Exception* nonnull %alloca29), !dbg !18 unreachable, !dbg !18 try.landingpad: ; preds = %fail49 %try.landingpad74 = landingpad { i8*, %Exception* } catch i32* @exn.9, !dbg !33 %exn75 = extractvalue { i8*, %Exception* } %try.landingpad74, 1, !dbg !33 %exnidptr = getelementptr %Exception, %Exception* %exn75, i64 0, i32 0, !dbg !32 %exnid = load i32, i32* %exnidptr, align 4, !dbg !32 %expected_id = load i32, i32* @exn.9, align 4, !dbg !33 %exncheck = icmp eq i32 %exnid, %expected_id, !dbg !33 br i1 %exncheck, label %try.handler, label %try.dispatcher_cont, !dbg !33 succ48: ; preds = %succ27 ret void, !dbg !33 fail49: ; preds = %succ27 %alloca50 = alloca %Exception, align 8, !dbg !32 %exn.id51 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 0, !dbg !32 store i32 9, i32* %exn.id51, align 8, !dbg !32 %exn.msg52.repack = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 5, i32 0, !dbg !32 store i8* getelementptr inbounds ([30 x i8], [30 x i8]* @const, i64 0, i64 0), i8** %exn.msg52.repack, align 8, !dbg !32 %exn.msg52.repack7 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 5, i32 1, !dbg !32 store i64 29, i64* %exn.msg52.repack7, align 8, !dbg !32 %exn.param53 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 6, !dbg !32 store i64 100, i64* %exn.param53, align 8, !dbg !32 %exn.param54 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 7, !dbg !32 store i64 %load, i64* %exn.param54, align 8, !dbg !32 %exn.param55 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 8, !dbg !32 store i64 0, i64* %exn.param55, align 8, !dbg !32 %file_ptr56.repack = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 1, i32 0, !dbg !32 store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %file_ptr56.repack, align 8, !dbg !32 %file_ptr56.repack8 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 1, i32 1, !dbg !32 store i64 62, i64* %file_ptr56.repack8, align 8, !dbg !32 %row_ptr57 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 2, !dbg !32 store i32 32, i32* %row_ptr57, align 8, !dbg !32 %col_ptr58 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 3, !dbg !32 store i32 15, i32* %col_ptr58, align 4, !dbg !32 %name_ptr59.repack = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 4, i32 0, !dbg !32 store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %name_ptr59.repack, align 8, !dbg !32 %name_ptr59.repack9 = getelementptr inbounds %Exception, %Exception* %alloca50, i64 0, i32 4, i32 1, !dbg !32 store i64 19, i64* %name_ptr59.repack9, align 8, !dbg !32 invoke void @__nac3_raise(%Exception* nonnull %alloca50) to label %after.raise unwind label %try.landingpad, !dbg !32 after.raise: ; preds = %fail49 unreachable, !dbg !32 try.handler: ; preds = %try.landingpad %alloca62 = alloca %Exception, align 8, !dbg !33 %exn.id63 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 0, !dbg !33 store i32 11, i32* %exn.id63, align 8, !dbg !33 %exn.msg64.repack = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 5, i32 0, !dbg !33 store i8* getelementptr inbounds ([3 x i8], [3 x i8]* @const.6, i64 0, i64 0), i8** %exn.msg64.repack, align 8, !dbg !33 %exn.msg64.repack10 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 5, i32 1, !dbg !33 store i64 2, i64* %exn.msg64.repack10, align 8, !dbg !33 %exn.param65 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 6, !dbg !33 %exn.str.repack = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 1, i32 0, !dbg !33 %1 = bitcast i64* %exn.param65 to i8*, !dbg !33 call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(24) %1, i8 0, i64 24, i1 false), !dbg !33 %exn.str.repack11 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 1, i32 1, !dbg !33 %exn.str68.repack = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 4, i32 0, !dbg !33 %exn.str68.repack12 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 4, i32 1, !dbg !33 %exn.ints = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 2, !dbg !33 %exn.ints69 = getelementptr inbounds %Exception, %Exception* %alloca62, i64 0, i32 3, !dbg !33 store i8* getelementptr inbounds ([63 x i8], [63 x i8]* @const.1, i64 0, i64 0), i8** %exn.str.repack, align 8, !dbg !33 store i64 62, i64* %exn.str.repack11, align 8, !dbg !33 store i32 34, i32* %exn.ints, align 8, !dbg !33 store i32 13, i32* %exn.ints69, align 4, !dbg !33 store i8* getelementptr inbounds ([20 x i8], [20 x i8]* @const.2, i64 0, i64 0), i8** %exn.str68.repack, align 8, !dbg !33 store i64 19, i64* %exn.str68.repack12, align 8, !dbg !33 call void @__nac3_raise(%Exception* nonnull %alloca62), !dbg !33 unreachable, !dbg !33 try.dispatcher_cont: ; preds = %try.landingpad call void @__nac3_resume(), !dbg !33 unreachable, !dbg !33 } ; Function Attrs: noreturn declare void @__nac3_raise(%Exception*) local_unnamed_addr #0 ; Function Attrs: noreturn declare void @__nac3_resume() local_unnamed_addr #0 ; Function Attrs: mustprogress nofree nosync nounwind willreturn declare i8* @llvm.stacksave() #1 declare void @rpc_send(i32, { i8*, i64 }*, i8**) local_unnamed_addr ; Function Attrs: mustprogress nofree nosync nounwind willreturn declare void @llvm.stackrestore(i8*) #1 declare i32 @rpc_recv(i8*) local_unnamed_addr ; Function Attrs: argmemonly nofree nounwind willreturn writeonly declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #2 ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #3 ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #3 attributes #0 = { noreturn } attributes #1 = { mustprogress nofree nosync nounwind willreturn } attributes #2 = { argmemonly nofree nounwind willreturn writeonly } attributes #3 = { argmemonly nofree nosync nounwind willreturn } !llvm.module.flags = !{!0, !1} !llvm.dbg.cu = !{!2, !5, !7, !8} !0 = !{i32 2, !"Debug Info Version", i32 3} !1 = !{i32 2, !"Dwarf Version", i32 4} !2 = distinct !DICompileUnit(language: DW_LANG_Python, file: !3, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false) !3 = !DIFile(filename: "<nac3_synthesized_modinit>", directory: ".") !4 = !{} !5 = distinct !DICompileUnit(language: DW_LANG_Python, file: !6, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false) !6 = !DIFile(filename: "/home/cresc/code/nac3/work1/nac3/my_expr/artiq/./debug_info.py", directory: ".") !7 = distinct !DICompileUnit(language: DW_LANG_Python, file: !6, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false) !8 = distinct !DICompileUnit(language: DW_LANG_Python, file: !6, producer: "NAC3", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !4, splitDebugInlining: false) !9 = distinct !DISubprogram(name: "__modinit__", linkageName: "__modinit__", scope: null, file: !3, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !4) !10 = !DISubroutineType(flags: DIFlagPublic, types: !11) !11 = !{!12} !12 = !DIBasicType(name: "_", flags: DIFlagPublic) !13 = !DILocation(line: 2, column: 5, scope: !14) !14 = distinct !DILexicalBlock(scope: !9, file: !3, line: 2, column: 5) !15 = distinct !DISubprogram(name: "__main__.Demo.run.0", linkageName: "__main__.Demo.run.0", scope: null, file: !6, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !8, retainedNodes: !4) !16 = !DILocation(line: 29, column: 33, scope: !17) !17 = distinct !DILexicalBlock(scope: !15, file: !6, line: 29, column: 9) !18 = !DILocation(line: 30, column: 12, scope: !17) !19 = !{!"branch_weights", i32 2000, i32 1} !20 = !DILocation(line: 29, column: 22, scope: !17) !21 = !DILocation(line: 12, column: 9, scope: !22, inlinedAt: !24) !22 = distinct !DILexicalBlock(scope: !23, file: !6, line: 12, column: 9) !23 = distinct !DISubprogram(name: "__main__.A.__init__.0", linkageName: "__main__.A.__init__.0", scope: null, file: !6, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !5, retainedNodes: !4) !24 = distinct !DILocation(line: 29, column: 22, scope: !17) !25 = !DILocation(line: 0, scope: !17) !26 = !DILocation(line: 29, column: 40, scope: !17) !27 = !{!"branch_weights", i32 1, i32 2000} !28 = !DILocation(line: 16, column: 21, scope: !29, inlinedAt: !31) !29 = distinct !DILexicalBlock(scope: !30, file: !6, line: 16, column: 9) !30 = distinct !DISubprogram(name: "__main__.A.info.0", linkageName: "__main__.A.info.0", scope: null, file: !6, type: !10, flags: DIFlagPublic, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !7, retainedNodes: !4) !31 = distinct !DILocation(line: 30, column: 12, scope: !17) !32 = !DILocation(line: 32, column: 16, scope: !17) !33 = !DILocation(line: 34, column: 31, scope: !17) ``` </details> but the traceback will still fail UNLESS we take the following patch to set the optimization level to `None` (`Less` does not work, either) when creating target machine: ```diff diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index d6ed943..0f88aaf 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -847,7 +847,7 @@ impl Nac3 { &triple, "", &features, - OptimizationLevel::Default, + OptimizationLevel::None, RelocMode::PIC, CodeModel::Default, ) ```
ychenfo force-pushed debug_info from 67d52b93a0 to 5c9c8c19b3 2022-04-18 02:23:57 +08:00 Compare
Author
Collaborator

AFAIK the "standard" in Python would be <nac3_synthesized_modinit>

Thanks! force-pushed to change the internal names to be enclosed by <>

> AFAIK the "standard" in Python would be <nac3_synthesized_modinit> Thanks! force-pushed to change the internal names to be enclosed by `<>`
ychenfo force-pushed debug_info from 5c9c8c19b3 to a0d170ab41 2022-04-20 03:59:49 +08:00 Compare
ychenfo force-pushed debug_info from a0d170ab41 to a722386b72 2022-04-20 04:04:01 +08:00 Compare
ychenfo force-pushed debug_info from a722386b72 to 5cfd308bb1 2022-04-21 00:55:11 +08:00 Compare
ychenfo force-pushed debug_info from 5cfd308bb1 to 8fa8da9a94 2022-04-21 15:11:33 +08:00 Compare
ychenfo force-pushed debug_info from 8fa8da9a94 to 16801eec72 2022-04-21 19:41:28 +08:00 Compare
sb10q requested review from pca006132 2022-04-22 09:12:13 +08:00
ychenfo force-pushed debug_info from 16801eec72 to 397b04f1b8 2022-04-22 21:23:52 +08:00 Compare
Author
Collaborator

Just to note down some more minimized examples that would cause the location info to disappear (setting OptimizationLevel::None when creating target machine can still bring them back):

lll = [4,5,1,8]

@nac3
class A:
        a: Kernel[int32]
            
        @kernel
        def __init__(self, a: Option[int32]):
            self.a = lll[100]
            self.a = a.unwrap()
            

        @kernel
        def info(self) -> int32:
            output(self.a)
            return self.a + 4

@nac3
class IdleKernel(EnvExperiment):
    core: KernelInvariant[Core]
        
    def build(self):
        self.setattr_device("core")
    
    @kernel
    def run(self):
        # raise IndexError("")  # have loc info
        # lll[5]	        # no loc info
        # A(none) 	        # have loc info, no matter `lll[100]` or `a.unwrap()` in `A.__init__`
        try:
            pass
        except IndexError:	# no loc info, no matter `IndexError` or any other exception or nothing here
            pass
        finally:
            # raise IndexError("finally")  # no loc info as long as any line that may raise 
            [0][1]                         # exception before the try catch block, else have loc info

So it seems that the control flow did matters.. guess that it is indeed the optimization which causes the location information to be invalid, plan to look more into how llvm-dwarfdump can help

Just to note down some more minimized examples that would cause the location info to disappear (setting `OptimizationLevel::None` when creating target machine can still bring them back): ```python lll = [4,5,1,8] @nac3 class A: a: Kernel[int32] @kernel def __init__(self, a: Option[int32]): self.a = lll[100] self.a = a.unwrap() @kernel def info(self) -> int32: output(self.a) return self.a + 4 @nac3 class IdleKernel(EnvExperiment): core: KernelInvariant[Core] def build(self): self.setattr_device("core") @kernel def run(self): # raise IndexError("") # have loc info # lll[5] # no loc info # A(none) # have loc info, no matter `lll[100]` or `a.unwrap()` in `A.__init__` try: pass except IndexError: # no loc info, no matter `IndexError` or any other exception or nothing here pass finally: # raise IndexError("finally") # no loc info as long as any line that may raise [0][1] # exception before the try catch block, else have loc info ``` So it seems that the control flow did matters.. guess that it is indeed the optimization which causes the location information to be invalid, plan to look more into how `llvm-dwarfdump` can help
sb10q reviewed 2022-05-08 18:02:14 +08:00
@ -554,0 +577,4 @@
|| "<nac3_internal>".to_string(),
|f| {
let name = f.location.file.0.to_string();
if name.contains("__nac3_synthesized_modinit__") {
Owner

Why contains and not ==?

Why ``contains`` and not ``==``?
Owner

Also can we simply call it <nac3_synthesized_modinit> in the first place (i.e. when calling parse_program), or is it causing problems?

Also can we simply call it ``<nac3_synthesized_modinit>`` in the first place (i.e. when calling ``parse_program``), or is it causing problems?
Owner

This special case also goes against the nac3core/nac3artiq separation, we should avoid nac3artiq-specific code in nac3core.

This special case also goes against the nac3core/nac3artiq separation, we should avoid nac3artiq-specific code in nac3core.
Author
Collaborator

Indeed calling <nac_synthesized_modinit> in the first place should be the best, force-pushed to update this, thanks!

Indeed calling `<nac_synthesized_modinit>` in the first place should be the best, force-pushed to update this, thanks!
ychenfo force-pushed debug_info from 397b04f1b8 to a022005183 2022-05-11 03:54:17 +08:00 Compare
sb10q changed title from WIP: Debug Location Info to Debug Location Info 2022-05-11 07:40:12 +08:00
sb10q merged commit a022005183 into master 2022-05-11 07:40:19 +08:00
sb10q deleted branch debug_info 2022-05-11 07:40:19 +08:00
Sign in to join this conversation.
No reviewers
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: M-Labs/nac3#267
No description provided.