From 744950d1d3cc6caaf8c22c591cd005bdedf83206 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Wed, 25 Nov 2009 23:28:01 +0000 Subject: [PATCH] Update to reflect recent debugging information encoding changes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89896 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/SourceLevelDebugging.html | 327 ++++++++++++--------------------- 1 file changed, 113 insertions(+), 214 deletions(-) diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html index 9e919bc2985..c4055753eae 100644 --- a/docs/SourceLevelDebugging.html +++ b/docs/SourceLevelDebugging.html @@ -37,15 +37,10 @@
  • Debugger intrinsic functions
  • -
  • Representing stopping points in the - source program
  • +
  • Object lifetimes and scoping
  • C/C++ front-end specific debug information
    1. C/C++ source file information
    2. @@ -761,92 +756,6 @@ DW_TAG_return_variable = 258 - - - -
      -
      -  void %llvm.dbg.stoppoint( uint, uint, metadata)
      -
      - -

      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.

      - -
      - - - - -
      -
      -  void %llvm.dbg.func.start( metadata )
      -
      - -

      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.

      - -
      - - - - -
      -
      -  void %llvm.dbg.region.start( metadata )
      -
      - -

      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.

      - - -
      - - - - -
      -
      -  void %llvm.dbg.region.end( metadata )
      -
      - -

      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.dbg.declare @@ -865,40 +774,6 @@ DW_TAG_return_variable = 258
      - - - -
      - -

      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.

      - -
      -
      Object lifetimes and scoping @@ -914,21 +789,20 @@ DW_TAG_return_variable = 258 scoping in this sense, and does not want to be tied to a language's scoping rules.

      -

      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.  }
       
      @@ -937,99 +811,124 @@ DW_TAG_return_variable = 258
      -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.

      +
      +
       
      +     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 ]   
      +   
      +
      -

      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.

      +

      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.

      -

      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).

      +

      Now lets take another example.

      -

      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.

      +
      +
       
      +     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}
      +   
      +
      -

      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.

      +

      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.