Understanding how to use of debugger intrinsic functions

I see debugger intrinsic functions like @llvm.dbg.declare appear in
the .ll generated with -g. But I still don't understand how it is
used.

https://llvm.org/docs/SourceLevelDebugging.html#debugger-intrinsic-functions

For the following C program, I got the relevant text in the .ll file
pasted below and the relevant metadata (listed using depth-first
search).

Does @llvm.dbg.declare actually translate to some machine code similar
to other user-defined functions? It seems that it only describes the
data types. Will they be translated to a native debugging format to
store along with the executable?

Can they be used for binary instrumentations? Thanks.

//////
#include <stdio.h>

int f(int i) {
    return i + 1;
}

int main(int argc, char *argv[1]) {
    if(f(argc)) {
        puts("Hello World!");
    }
    return 0;
}
//////

define i32 @main(i32 %arg, i8** %arg1) #0 !dbg !17 {
...
  store i32 %arg, i32* %tmp2, align 4
  call void @llvm.dbg.declare(metadata i32* %tmp2, metadata !23,
metadata !DIExpression()), !dbg !24
...

!23 = !DILocalVariable(name: "argc", arg: 1, scope: !17, file: !1,
line: 8, type: !11)

!17 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line:
8, type: !18, isLocal: false, isDefinition: true, scopeLine: 8, flags:
DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!1 = !DIFile(filename: "../test_data/main.c", directory:
"/Users/pengy/linux/bin/wrappercomposite/src/xplat/llvmxplat/src/lvll2/lvll2fundbi/llin2funbodyraw0/main")
!18 = !DISubroutineType(types: !19)
!19 = !{!11, !11, !20}
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !21, size: 64)
!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64)
!22 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)

!24 = !DILocation(line: 8, column: 14, scope: !17)

From: llvm-dev [mailto:llvm-dev-bounces@lists.llvm.org] On Behalf Of Peng
Yu via llvm-dev
Sent: Monday, January 28, 2019 7:37 PM
To: llvm-dev
Subject: [llvm-dev] Understanding how to use of debugger intrinsic
functions

I see debugger intrinsic functions like @llvm.dbg.declare appear in
the .ll generated with -g. But I still don't understand how it is
used.

Source Level Debugging with LLVM — LLVM 18.0.0git documentation
functions

For the following C program, I got the relevant text in the .ll file
pasted below and the relevant metadata (listed using depth-first
search).

Does @llvm.dbg.declare actually translate to some machine code similar
to other user-defined functions? It seems that it only describes the
data types. Will they be translated to a native debugging format to
store along with the executable?

@llvm.dbg.declare associates the `alloca` for a variable with its
debug-info metadata description. It does not translate into machine
code, but provides information for the production of DWARF or CodeView
debug info in the object file.

The existence of debug info is not supposed to change anything about
machine code generation. This "supposed to" is not perfect, but that
is the goal. Some of us believe that using IR instructions to supply
debug information is an anti-pattern, and it has certainly been a source
of bugs over the years where optimization passes forget to accommodate
or ignore debug-info instructions correctly, but so far nobody has had
the time available to design a different mechanism.

Can they be used for binary instrumentations? Thanks.

I don't see how, but that's not really an area I'm familiar with.
--paulr