From cacef07c20f9dbeb8568426a4e84d8e45c14fa21 Mon Sep 17 00:00:00 2001
From: Devang Patel This intrinsic is used to provide correspondence between the source file and
- the generated code. The first argument is the line number (base 1), second
- argument is the column number (0 if unknown) and the third argument the
- source %llvm.dbg.compile_unit.
- Code following a call to this intrinsic will
- have been defined in close proximity of the line, column and file. This
- information holds until the next call
- to %lvm.dbg.stoppoint. This intrinsic is used to link the debug information
- in %llvm.dbg.subprogram to the
- function. It defines the beginning of the function's declarative region
- (scope). It also implies a call to
- %llvm.dbg.stoppoint which
- defines a source line "stop point". The intrinsic should be called early in
- the function after the all the alloca instructions. It should be paired off
- with a closing
- %llvm.dbg.region.end.
- The function's single argument is
- the %llvm.dbg.subprogram.type. This intrinsic is used to define the beginning of a declarative scope (ex.
- block) for local language elements. It should be paired off with a closing
- %llvm.dbg.region.end. The
- function's single argument is
- the %llvm.dbg.block which is
- starting. This intrinsic is used to define the end of a declarative scope (ex. block)
- for local language elements. It should be paired off with an
- opening %llvm.dbg.region.start
- or %llvm.dbg.func.start.
- The function's single argument is either
- the %llvm.dbg.block or
- the %llvm.dbg.subprogram.type
- which is ending. LLVM debugger "stop points" are a key part of the debugging representation
- that allows the LLVM to maintain simple semantics
- for debugging optimized code. The basic idea is that
- the front-end inserts calls to
- the %llvm.dbg.stoppoint
- intrinsic function at every point in the program where a debugger should be
- able to inspect the program (these correspond to places a debugger stops when
- you "step" through it). The front-end can choose to place these as
- fine-grained as it would like (for example, before every subexpression
- evaluated), but it is recommended to only put them after every source
- statement that includes executable code. Using calls to this intrinsic function to demark legal points for the
- debugger to inspect the program automatically disables any optimizations that
- could potentially confuse debugging information. To
- non-debug-information-aware transformations, these calls simply look like
- calls to an external function, which they must assume to do anything
- (including reading or writing to any part of reachable memory). On the other
- hand, it does not impact many optimizations, such as code motion of
- non-trapping instructions, nor does it impact optimization of subexpressions,
- code duplication transformations, or basic-block reordering
- transformations.
- void %llvm.dbg.stoppoint( uint, uint, metadata)
-
-
-
- void %llvm.dbg.func.start( metadata )
-
-
-
- void %llvm.dbg.region.start( metadata )
-
-
-
- void %llvm.dbg.region.end( metadata )
-
-
-
In order to handle this, the LLVM debug format uses the notion of "regions" - of a function, delineated by calls to intrinsic functions. These intrinsic - functions define new regions of the program and indicate when the region - lifetime expires. Consider the following C fragment, for example:
+In order to handle this, the LLVM debug format uses the metadata attached + with llvm instructions to encode line nuber and scoping information. + Consider the following C fragment, for example:
1. void foo() {
-2. int X = ...;
-3. int Y = ...;
+2. int X = 21;
+3. int Y = 22;
4. {
-5. int Z = ...;
-6. ...
+5. int Z = 23;
+6. Z = X;
7. }
-8. ...
+8. X = Y;
9. }
-void %foo() {
+nounwind ssp {
entry:
- %X = alloca int
- %Y = alloca int
- %Z = alloca int
-
- ...
-
- call void @llvm.dbg.func.start( metadata !0)
-
- call void @llvm.dbg.stoppoint( uint 2, uint 2, metadata !1)
-
- call void @llvm.dbg.declare({}* %X, ...)
- call void @llvm.dbg.declare({}* %Y, ...)
-
- ;; Evaluate expression on line 2, assigning to X.
-
- call void @llvm.dbg.stoppoint( uint 3, uint 2, metadata !1)
-
- ;; Evaluate expression on line 3, assigning to Y.
-
- call void @llvm.region.start()
- call void @llvm.dbg.stoppoint( uint 5, uint 4, metadata !1)
- call void @llvm.dbg.declare({}* %X, ...)
-
- ;; Evaluate expression on line 5, assigning to Z.
-
- call void @llvm.dbg.stoppoint( uint 7, uint 2, metadata !1)
- call void @llvm.region.end()
-
- call void @llvm.dbg.stoppoint( uint 9, uint 2, metadata !1)
-
- call void @llvm.region.end()
-
- ret void
+ %X = alloca i32, align 4 ; [#uses=4]
+ %Y = alloca i32, align 4 ; [#uses=4]
+ %Z = alloca i32, align 4 ; [#uses=3]
+ %0 = bitcast i32* %X to { }* ; <{ }*> [#uses=1]
+ call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7
+ store i32 21, i32* %X, !dbg !8
+ %1 = bitcast i32* %Y to { }* ; <{ }*> [#uses=1]
+ call void @llvm.dbg.declare({ }* %1, metadata !9), !dbg !10
+ store i32 22, i32* %Y, !dbg !11
+ %2 = bitcast i32* %Z to { }* ; <{ }*> [#uses=1]
+ call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
+ store i32 23, i32* %Z, !dbg !15
+ %tmp = load i32* %X, !dbg !16 ; [#uses=1]
+ %tmp1 = load i32* %Y, !dbg !16 ; [#uses=1]
+ %add = add nsw i32 %tmp, %tmp1, !dbg !16 ; [#uses=1]
+ store i32 %add, i32* %Z, !dbg !16
+ %tmp2 = load i32* %Y, !dbg !17 ; [#uses=1]
+ store i32 %tmp2, i32* %X, !dbg !17
+ ret void, !dbg !18
}
+
+declare void @llvm.dbg.declare({ }*, metadata) nounwind readnone
+
+!0 = metadata !{i32 459008, metadata !1, metadata !"X",
+ metadata !3, i32 2, metadata !6}; [ DW_TAG_auto_variable ]
+!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", metadata !"foo",
+ metadata !"foo", metadata !3, i32 1, metadata !4,
+ i1 false, i1 true}; [DW_TAG_subprogram ]
+!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"foo.c",
+ metadata !"/private/tmp", metadata !"clang 1.1", i1 true,
+ i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
+!4 = metadata !{i32 458773, metadata !3, metadata !"", null, i32 0, i64 0, i64 0,
+ i64 0, i32 0, null, metadata !5, i32 0}; [DW_TAG_subroutine_type ]
+!5 = metadata !{null}
+!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0,
+ i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
+!7 = metadata !{i32 2, i32 7, metadata !1, null}
+!8 = metadata !{i32 2, i32 3, metadata !1, null}
+!9 = metadata !{i32 459008, metadata !1, metadata !"Y", metadata !3, i32 3,
+ metadata !6}; [ DW_TAG_auto_variable ]
+!10 = metadata !{i32 3, i32 7, metadata !1, null}
+!11 = metadata !{i32 3, i32 3, metadata !1, null}
+!12 = metadata !{i32 459008, metadata !13, metadata !"Z", metadata !3, i32 5,
+ metadata !6}; [ DW_TAG_auto_variable ]
+!13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
+!14 = metadata !{i32 5, i32 9, metadata !13, null}
+!15 = metadata !{i32 5, i32 5, metadata !13, null}
+!16 = metadata !{i32 6, i32 5, metadata !13, null}
+!17 = metadata !{i32 8, i32 3, metadata !1, null}
+!18 = metadata !{i32 9, i32 1, metadata !2, null}
This example illustrates a few important details about the LLVM debugging - information. In particular, it shows how the various intrinsics are applied + information. In particular, it shows how the llvm.dbg.declare intrinsic + and location information, attached with an instruction, are applied together to allow a debugger to analyze the relationship between statements, variable definitions, and the code used to implement the function.
-The first - intrinsic %llvm.dbg.func.start - provides a link with the subprogram - descriptor containing the details of this function. This call also - defines the beginning of the function region, bounded by - the %llvm.region.end at the - end of the function. This region is used to bracket the lifetime of - variables declared within. For a function, this outer region defines a new - stack frame whose lifetime ends when the region is ended.
- -It is possible to define inner regions for short term variables by using the - %llvm.region.start - and %llvm.region.end to - bound a region. The inner region in this example would be for the block - containing the declaration of Z.
- -Using regions to represent the boundaries of source-level functions allow - LLVM interprocedural optimizations to arbitrarily modify LLVM functions - without having to worry about breaking mapping information between the LLVM - code and the and source-level program. In particular, the inliner requires - no modification to support inlining with debugging information: there is no - explicit correlation drawn between LLVM functions and their source-level - counterparts (note however, that if the inliner inlines all instances of a - non-strong-linkage function into its caller that it will not be possible for - the user to manually invoke the inlined function from a debugger).
- -Once the function has been defined, - the stopping point - corresponding to line #2 (column #2) of the function is encountered. At this - point in the function, no local variables are live. As lines 2 and 3 - of the example are executed, their variable definitions are introduced into - the program using - %llvm.dbg.declare, without the - need to specify a new region. These variables do not require new regions to - be introduced because they go out of scope at the same point in the program: - line 9.
- -In contrast, the Z variable goes out of scope at a different time, - on line 7. For this reason, it is defined within the inner region, which - kills the availability of Z before the code for line 8 is executed. - In this way, regions can support arbitrary source-language scoping rules, as - long as they can only be nested (ie, one scope cannot partially overlap with - a part of another scope).
- -It is worth noting that this scoping mechanism is used to control scoping of - all declarations, not just variable declarations. For example, the scope of - a C++ using declaration is controlled with this and could change how name - lookup is performed.
- +
+ call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7
+
+ This first intrinsic + %llvm.dbg.declare + encodes debugging information for variable X. The metadata, + !dbg !7 attached with the intrinsic provides scope information for + the variable X.
+
+ !7 = metadata !{i32 2, i32 7, metadata !1, null}
+ !1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+ !2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo",
+ metadata !"foo", metadata !"foo", metadata !3, i32 1,
+ metadata !4, i1 false, i1 true}; [DW_TAG_subprogram ]
+
+ Here !7 is a metadata providing location information. It has four + fields : line number, column number, scope and original scope. The original + scope represents inline location if this instruction is inlined inside + a caller. It is null otherwise. In this example scope is encoded by + !1. !1 represents a lexical block inside the scope + !2, where !2 is a + subprogram descriptor. + This way the location information attched with the intrinsics indicates + that the variable X is declared at line number 2 at a function level + scope in function foo.
+ +Now lets take another example.
+ +
+ call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
+
+ This intrinsic + %llvm.dbg.declare + encodes debugging information for variable Z. The metadata, + !dbg !14 attached with the intrinsic provides scope information for + the variable Z.
+
+ !13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
+ !14 = metadata !{i32 5, i32 9, metadata !13, null}
+
+ Here !14 indicates that Z is declaread at line number 5, + column number 9 inside a lexical scope !13. This lexical scope + itself resides inside lexcial scope !1 described above.
+ +The scope information attached with each instruction provides a straight + forward way to find instructions covered by a scope.
-- cgit v1.1