On Thu, Jun 5, 2014 at 7:55 AM, Keno Fischer
<kfischer at college.harvard.edu> wrote:> Hello everybody,
>
> I'm working on adding debug info support for julia and have a few
questions
> about the llvm.dbg intrinsics. Sorry if this is a little long. If any of
the
> things I'm asking about aren't currently possible in LLVM, I'd
be more than
> happy to work on them, if I can get some advice on the general direction
> (e.g. can everything be retrofitted onto the existing intrinsics or do I
> need new ones, etc.)
>
> My first question is as follows. Consider the following llvm IR (exerted
> from a Julia try/catch block)
>
> call void @llvm.dbg.value(metadata !{%jl_value_t* %16}, i64 0, metadata
> !19)
> %17 = getelementptr %jl_value_t** %1, i64 1, !dbg !15
> %18 = load %jl_value_t** %17, !dbg !15
> call void @llvm.dbg.value(metadata !{%jl_value_t* %18}, i64 0, metadata
> !20)
> store i1 false, i1* %"#s55", !dbg !21
> %19 = getelementptr i8* %14, i64 0, !dbg !21
> call void @jl_enter_handler(i8* %19), !dbg !21
> %20 = call i32 @sigsetjmp(i8* %19, i32 0), !dbg !21
> %21 = icmp eq i32 %20, 0, !dbg !21
> br i1 %21, label %try, label %L, !dbg !21
>
> try: ; preds = %top
> call void inttoptr (i64 4295956000 to void ()*)(), !dbg !22
> %22 = getelementptr %jl_value_t** %4, i64 1, !dbg !22
> store %jl_value_t* %18, %jl_value_t** %22, !dbg !22
> call void @llvm.dbg.declare(metadata !{%jl_value_t** %22}, metadata !20)
>
> The generated corresponding DWARF info is (corresponding to !20):
>
> AT_location( 0x0000005f
> 0x00000001142f4000 - 0x00000001142f40b2: rsi
> 0x00000001142f40b2 - 0x00000001142f40c3: rsp+104
> 0x00000001142f4115 - 0x00000001142f4153: rax
> 0x00000001142f4153 - 0x00000001142f4155: rsp+56 )
>
> Now 0x00000001142f40c3 is the location of the `call void
> @jl_enter_handler(i8* %19)`. So there's a gap in the debug info from
there
> until the next declare. I would like to understand why this is the case and
> what to do about it (note that %18 is still used later, so it's not the
case
> that it goes out of scope, the stack location is still valid).
Location tracking is pretty simplistic and brittle at the moment. LLVM
can manage the allocas that Clang generates and produce debug info
describing the location of the variable as being in that stack slot
for the entire range of the function. Beyond that it's very
hit-and-miss. Notably, LLVM only describes the range of non-alloca
variables as from their definition (where the register is initialized,
or the register offset is written to, etc) to the end of that basic
block. This completely kills lots of perfectly good debug info.
There's a review underway to partially fix this (
http://reviews.llvm.org/D3933 ) though it's still fairly restrictive.
I've made comments on there about where I /think/ the fix should be
(it looks like there's code already there to handle it and it's not
working at the moment?), maybe.
> My second question is about variables that live at multiple locations. The
> DWARF standard supports overlapping address ranges and in Julia a variable
> might be in several locations at once and I'd love to just be able to
> declare them all and have llvm figure out the appropriate ranges. Some
> examples of where the variable might live are:
>
> - In the argument array passed to a function (for certain functions we pass
> an array
> of boxed pointers on the stack)
> - In a GC slot
> - Loaded into registers
>
> Sometimes these overlap, so I feel like I ought to just put all of that
> information into the debug info and have the debugger figure it out. Is
> there anyway to declare overlapping ranges?
Nope, I don't think LLVM has /any/ concept/support for describing
multiple locations simultaneously. It could be added. Shouldn't be
totally heinous to do so, but given the limitations described above,
it's certainly not the first priority, especially if the variable is
live in something like a stack slot forever... it's easy just to
describe that location & skip the rest. Such support could potentially
be added in the DbgValueHistoryCalculator being worked on/modified in
the above review.
> My third question is related to the argument array. In particular, it
should
> be always possible for the debugger to find out where the argument array is
> by looking at the gc frame of the calling function and then taking an
> appropriate offset. I realize this is probably very fancy, but it seems to
> me that it should be possible to encode this into a DWARF expression and
> have it just work in the debugger. I'm not sure it is feasible to
express
> this directly using LLVM intrinsics, but it should be fairly
straightforward
> to write myself. Do the necessary hooks exist in LLVM to do something like
> this (ideally llvm would determine the appropriate address ranges and
I'd
> just provide the single location information a a DWARF expression). If this
> capability doesn't exist yet, I'd appreciate some pointer about
where to add
> it.
>
> Thanks for reading and I apologize that this has gotten so long. At some
> point I might have to move some of the more fancy functionality to the
> custom debugger, side but I'd prefer to encode as much as possible
directly
> into DWARF, so I want to see how far I can get just with that.
>
> Thanks,
> Keno
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>