Possible to avoid llvm.dbg.value intrinsics?

I am currently trying to map all LLVM instructions of a program to their respective locations in the source code, wherever possible. However, I found that in many cases I have to deal with llvm.dbg.value instructions, which are quite a bit more complex when it comes to mapping them to their right source location. Judging from the LLVM wiki, I understood that these intrinsics are introduced by optimization passes, and replace llvm.dbg.declare instructions. There it says:

A frontend should generate exactly one call to llvm.dbg.declare at the point of declaration of a source variable. Optimization passes that fully promote the variable from memory to SSA values will replace this call with possibly multiple calls to llvm.dbg.value.

So in theory I would have guessed that avoiding any optimizations, would also avoid any introduction of llvm.dbg.value instructions. And indeed, with smaller examples, this seems to be exactly the case. However, when I tried to compile larger software projects, such as bash or ngninx, I found that calls to llvm.dbg.value were still introduced, despite “-O0” clearly being passed to clang. Did I misinterpret something here and is there any other way to get rid of all calls to llvm.dbg.value in favor of calls to llvm.dbg.declare?


I’m not sure off the top of my head whether clang frontend emits dbg.values, and if it does under what conditions. If it does, I can’t imagine there being an easy way to control that. What does the IR containing the dbg.values look like, do you have a simple snippet you can share?

I might be able to offer suggestions for the problem you’re trying to solve, but I don’t fully understand what you’re trying to do:

I am currently trying to map all LLVM instructions of a program to their respective locations in the source code … llvm.dbg.value instructions, which are quite a bit more complex when it comes to mapping them to their right source location

Are you able to explain this further? Debug intrinsics (llvm.dbg.*) are meta-instructions that don’t correspond to any real instructions or source code. Not knowing what you are trying to do, I would naively imagine that all debugging intrinsics should be skipped/ignored.

You could compile with -gmlt to have no variable location descriptions emitted.

Sorry for the confusion, I am not trying to get the source location of the debug intrinsics, rather I want to use them to find the debug location of the original instruction, wrapped by them. Now with the llvm.dbg.declare instrinsic, I found they do have a debug location immediately attached, which makes it easy to retrieve the corresponding line in the source code. See below:

%1 = alloca [200 x i16], align 16
call void @llvm.dbg.declare(metadata [200 x i16]* %1, metadata !12788, metadata !DIExpression()), !dbg !12867
!12867 = !DILocation(line: 1687, column: 16, scope: !12782)

As can be seen, all I have to do is find the dbg.declare of the original alloca to get to the according DILocation. With the llvm.dbg.value intrinsic, there too is a !dbg location defined, but it seems to lead to a bogus location, e.g., something like this:

!10669 = !DILocation(line: 0, scope: !10648)

Only if I unwrap the second meta data argument of an llvm.dbg.value intrinsic, am I able to get to a DILocalVariable that contains the necessary information, which makes the software I am writing quite a bit more complex, since I always have to distinguish between the two cases and I have to treat the DILocations differently from the DILocalVariables.

As far as I understand, the dbg.value intrinsics are introduced through optimizations and replace dbg.declare intrinsics. Therefore, I was wondering if there is some way to prevent any sort of optimization replacing the declares. For small programs, passing -O0 to clang, does seem to work and the emitted bitcode contains no calls to llvm.dbg.value. However, trying to compile something larger, such as bash or nginx, the bitcode does contain such calls, despite -O0 apparently being passed during compilation.

Thank you, but am I correct with the assumption that passing -gmlt would simply get rid of the intrinsics entirely? Because this is not what I have in mind, I actually do want to gather as much info about the original source locations as possible. I merely want to avoid producing calls to llvm.dbg.value, in favor of llvm.dbg.declare. Sorry for the confusion, I suppose I didn’t express myself very clearly.

Ah, not sure then. I guess there’s probably some necessary transformations we run that end up greating dbg.values… reducing a test case, isolating which transformation triggers it, etc, might be insightful, but I’d guess the answer’s probably “that’s just necessary” in some situations.